文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

redis事务的示例分析

2024-04-02 19:55

关注

这篇文章将为大家详细讲解有关redis事务的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

一: 事务实战

具体到事务是什么,要保证什么。。。这个我想没必要说了,先不管三七二十一,看一下redis手册,领略下它的魔力。

redis事务的示例分析

1. multi,exec

还记得sqlserver是怎么玩的吗?一般都是这样的三个步骤,生成事务,产生命令,执行事务,对吧,而对应redis呢??multi就是生成事务,然后输入redis命令,最后用exec执行命令,就像下面这样:

redis事务的示例分析

可以看到,我set完命令之后,反馈信息是QUEUED,最后我再执行exec,这些命令才会真正的执行,就是这么的简单,一切执行的就是那么的顺利,一点都不拖泥带水,可能有些人说,其实事务中还有一个rollback操作,但好像在redis中没有看到,很遗憾是redis中没有rollback操作,比如下面这样。

redis事务的示例分析

在图中我故意用lpush命令去执行string,可想而知自然不会执行成功,但从结果中,你看到什么了呢?两个OK,一个Error,这就是违反了事务的原子性,但是我该怎么反驳呢??? reids仅仅是个数据结构服务器,多简单的一件事情,退一万步说,很明显的错误命令它会直接返回的,比如我故意把lpush写成lpush2:

redis事务的示例分析

2. watch

不知道你看完multi后面的三条set命令之后,有没有一种心虚的感觉,怎么说呢,就是只要命令是正确的,redis保证会一并执行,誓死完成任务,虽然说命令是一起执行的,但是谁可以保证我在执行命令的过程中,其他client不会修改这些值呢???如果修改了这些值,那我的exec还有什么意义呢???没关系,这种烂大街的需求,redis怎可能袖手旁观???这里的watch就可以助你一臂之力。

WATCH
WATCH key [key ...]

监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

上面就是redis手册中关于watch的解释,使用起来貌似很简单,就是我在multi之前,用watch去监视我要修改的key,如果说我在exec之前,multi之后的这段时间,key被其他client修改,那么exec就会执行失败,返回(nil),就这么简单,我还是来举个例子:

 redis事务的示例分析

二:原理探索

关于事务操作的源代码,大多都在redis源码中的multi.c 文件中,接下来我会一个一个的简单剖析一下:

1. multi

在redis的源代码中,它大概是这么写的:

void multiCommand(redisClient *c) {
   if (c->flags & REDIS_MULTI) {
     addReplyError(c,"MULTI calls can not be nested");
     return;
   }
   c->flags |= REDIS_MULTI;
   addReply(c,shared.ok);

从这段代码中,你可以看到multi只是简单的把redisClient的REDIS_MULTI状态打开,告诉这个redis客户端已经进入事务模式了。

2. 生成命令

在redisClient中,里面有一个multiState命令:

typedef struct redisClient {

  。。。

  multiState mstate;   

  。。。

} redisClient;

从注释中你大概也看到了这个命令和multi/exec肯定有关系,接下来我很好奇的看看multiState的定义:

typedef struct multiState {

  multiCmd *commands;   

  int count;       

  int minreplicas;    

  time_t minreplicas_timeout; 

} multiState;

从multiState这个枚举中,你可以看到下面有一个*command命令,从注释中可以看到它其实指向的是一个数组,它就是你的若干条命令啦。。。下面还有一个count,可以看到是实际的commands的总数。 

3. watch

为了方便说到后面的exec,这里想说一下watch大概是怎么实现的,在multi.c源代码中是这样写的。

typedef struct watchedKey {
   robj *key;
   redisDb *db;
 } watchedKey;
 
 void watchCommand(redisClient *c) {
   int j;
 
   if (c->flags & REDIS_MULTI) {
     addReplyError(c,"WATCH inside MULTI is not allowed");
     return;
   }
   for (j = 1; j < c->argc; j++)
     watchForKey(c,c->argv[j]);
   addReply(c,shared.ok);
 }
 
 
 void watchForKey(redisClient *c, robj *key) {
   list *clients = NULL;
   listIter li;
   listNode *ln;
   watchedKey *wk;
 
   
   listRewind(c->watched_keys,&li);
   while((ln = listNext(&li))) {
     wk = listNodeValue(ln);
     if (wk->db == c->db && equalStringObjects(key,wk->key))
       return; 
   }
   
   clients = dictFetchValue(c->db->watched_keys,key);
   if (!clients) {
     clients = listCreate();
     dictAdd(c->db->watched_keys,key,clients);
     incrRefCount(key);
   }
   listAddNodeTail(clients,c);
   
   wk = zmalloc(sizeof(*wk));
   wk->key = key;
   wk->db = c->db;
   incrRefCount(key);
   listAddNodeTail(c->watched_keys,wk);
 }

这段代码中大概最核心的一点就是:

  

  clients = dictFetchValue(c->db->watched_keys,key);

就是通过dicFetchValue这个字典方法,从watched_keys中找到指定key的value,而这个value是一个clients的链表,说明人家其实是想找到关于这个key的所有client,最后还会将本次key塞入到redisclient的watched_keys字典中,如下代码:

  

  wk = zmalloc(sizeof(*wk));

  wk->key = key;

  wk->db = c->db;

  incrRefCount(key);

  listAddNodeTail(c->watched_keys,wk);

如果非要画图,大概就是这样:

redis事务的示例分析

其中watched_key是个字典结构,字典的键为上面的key1,key2。。。,value为client的链表,这样的话,我就非常清楚某个key中是被哪些client监视着的。

4.exec

这个命令里面大概做了两件事情:

<1>:   判断c->flags=REDIS_DIRTY_EXEC 打开与否,如果是的话,取消事务discardTransaction(c),也就是说这个key已经被别的client修改了。

<2>:   如果没有修改,那么就for循环执行comannd[]中的命令,如下图中的两处信息:

  redis事务的示例分析

关于“redis事务的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯