We all know that redis is the pursuit of simple, fast, efficient, in this case also refused to support the window platform, sqlserver school time, we know that the transaction is a complicated thing, so if this copy to redis in redis, behoove is not as simple as pure things, but the transaction is, we write a program cannot escape the scene, so redis author eclectic wrote a simplified version of the transaction mechanism.
一:真正的战斗
具体是什么交易什么保证。我不认为这是必要的,先不管37二十一,看看使用手册和欣赏它的魔力。
1。多、高层
记得SQLServer玩过吗一般来说,这是三步,产生交易,产生的
命令,
执行交易,是
正确的,和对应的使用多是生成一个交易,然后进入Redis命令,然后执行命令的执行,如以下:
你看,我完成了
设置命令后,反馈信息是排队,最后我会执行exec,这些命令将真的实现了,就是这么简单,一切
都是那么的顺利,一点也不慢,有些人可能会说,事实上,交易有一个回滚
操作,但它似乎redis没有看到,不幸的是,在redis没有回滚操作,如以下。
在
图片中,我故意用lpush要执行的命令字符串,可想而知,自然不会执行成功,但从结果看,你看到了什么两个好,一个
错误,这是违反了事务的原子性,但我应该如何反驳Reids是一个数据结构
服务器。这是件简单的事。在一万步中,很明显,错误的指令会回来直接,例如,我特意写lpush为lpush1。
2。看
之后不知道三集命令你看到背后的多,没有人感到内疚,怎么说,只要
顺序正确,Redis的实施将确保完成
任务,虽然命令进行的,但谁能保证我在命令的执行过程中,其他客户不
修改这些值吗如果这些值被修改,我的执行官还意味着什么没关系,这个烂大街的需求,如何使用袖手旁观吗这里的表可以帮助你。
看
观察键{键}
监视一个(或多个)键,如果在执行事务之前由其他命令更改该键,则该事务将被中断。
手表的解释是上面的使用手册,它看起来很简单,我只是在多,看我修改的表的关键,如果我之前说的执行,经过这段时间的多,关键的其他客户端的修改,然后执行将失败,返回(无),我是如此简单,例如:
二:原理探索
对于该交易操作的源代码,主要是多。C
文件中使用的源代码,然后我会做一个简单的分析。
1。多种
在Redis的源代码,这可能是写的。
无效multicommand(redisclient×C){
如果(C—>旗redis_multi){
AddReplyError(C,多称不能嵌套);
返回;
}
C - >旗redis_multi | =;
addreply(C,共享吧);
从这段代码中,你可以看到多只打开redisclient的redis_multi状态,并告诉redis客户端已进入交易
模式。
2。生成命令
在redisclient,它有一个多态的命令:
redisclient { typedef struct
。
多状态MSTATE多/执行状态; / * * /
。
redisclient };
从注释中你也可以看到,这个命令是一定要多/执行相关的,然后我很好奇多态的定义:
typedef struct多态{
multicmd *命令阵列多命令; / * * /
int计算多个命令的总数;
国际minreplicas minreplicas
同步复制; / * * /
time_t minreplicas_timeout minreplicas超时UnixTime; / * * /
多态};
从各州的枚举,你可以看到下面有一个*命令。从注释中,可以看到它指向一个数组,这是您的一些命令。
三.看
为了更容易地讨论后面的执行
程序,这里有一个关于表如何可能完成的想法,它是在多C源代码中编写的。
watchedkey { typedef struct
robj *键;
redisdb *分贝;
watchedkey };
无效watchcommand(redisclient×C){
Int J;
如果(C—>旗redis_multi){
AddReplyError(C,看里面多是不允许的);
返回;
}
为(J = 1;J argc;j++)
WatchForKey(C,C -> argv {,});
addreply(C,共享吧);
}
注意指定的键*
无效watchforkey(redisclient * C,robj *键){
列表*客户端=空;
ListIter Li;
思路:* LN;
watchedkey *周;
检查我们是否已经在看这个键了。
ListRewind(C→watched_keys,李);
而(((Ln = listnext(李))){
周= listnodevalue(LN);
如果(WK ->分贝= = C - > DB equalstrinbjects(关键,WK—>键))
已监视返回密钥;
}
此密钥在这个数据库中还没有被监视。让我们加上它。
客户= dictfetchvalue(C ->数据库-> watched_keys,关键);
如果(!客户){
客户= listcreate();
DictAdd(C ->数据库-> watched_keys,关键客户);
incrrefcount(关键);
}
listaddnodetail(客户,C);
将新密钥添加到该客户端监视的密钥列表中。
周= zmalloc(sizeof(*周));
键=键;
周> db = C = db;
incrrefcount(关键);
ListAddNodeTail(C→watched_keys,周);
}
这个代码中最重要的一点是:
此密钥在这个数据库中还没有被监视。让我们加上它。
客户= dictfetchvalue(C ->数据库-> watched_keys,关键);
这本字典是通过dicfetchvalue
方法,从watched_keys找到指定的
核心价值,而价值是客户的名单,这表明人们实际上要重点
发现所有的客户端,最后将钥匙插入redisclient watched_keys词典中,下面的代码:
将新密钥添加到该客户端监视的密钥列表中。
周= zmalloc(sizeof(*周));
键=键;
周> db = C = db;
incrrefcount(关键);
ListAddNodeTail(C→watched_keys,周);
如果你不必画一幅画,那可能就是这样。
watched_key是字典的结构,并对字典的键key1,key2。价值是客户的名单,所以我非常了解的客户是在某个关键监测。
4.exec
这条命令有两件事要做:
判断C ->旗帜= redis_dirty_exec是否开放,如果是这样的话,
取消交易discardtransaction(C),也就是说,这已经被其他
用户修改关键。
如果没有进行修改,然后在comannd { }的命令是在循环执行,如下图的两个信息:
U3000 U3000
好吧,就是说,我希望能帮助你。
EndFragment