前段时间也读了下python的redis库的源码,看的时候也有些跳跃和粗糙,但是基本大概的过了下…. …. 越来越发现redis很是不简单…    有时间分享下对于redis库的一些理解。 

redis本身应对外部请求的是单任务的,也是多线程安全的,这个大家都应该知道的, 所以才会经常有人用redis做计数服务。 但是对于redis的事务处理,我一开始理解是有问题,先前以为multi  exec是可以保证绝对的原子的,以为他不单单是原子,而且还会加锁….  结果,不是的…  

原文链接是 xiaorui.cc    http://xiaorui.cc/?p=1394


     经过一顿bug带来的痛苦经历之后,才发现,我的理解居然是有问题的….    话说同事朱伟这段时间要分享redis的高级用法,上次他就针对redis经典案例讲了3个小时…. 他是读过redis源码的人…   跟他讨论了下redis事务之后,我自己总结并小范围测试下,总结了这篇文章,如果有不对的地方,请大家拍砖。。。。

multi exec ,他的原子只能是在其中的,没有锁的逻辑。 这个一定要注意,他只能保证,他里面的那堆命令不会被其他客户端的命令参杂在一起。

那么我们这里想一个问题,如果我有一个key是100数字,我们客户端配置了multi之后,要进行incr渐增,但是还没有incr操作的时候,张三也连入了redis,并且把key改成了200。

那么我继续incr的搞了好几次 … … 会发现incr和exec之后的结果是200+ ,按照官方的意思,这是对的,对不对要看你的场景。  要解决别人的干扰咋整?   继续看… 

redis在2.2之后加入了watch的功能, 那么watch是啥?  

WATCH 命令提供了在开始事务前监视一个或多个键的能力。如果这些键中的任何一个在执行事务前发生改变,整个事务就会被取消并抛出 WatchError 异常。

watch是监控key的时候,如果数据有变动的话,multi exec会失败的… 如果没有变动,那么就正常推送进去。    看下面的测试,我们注意到了redis的return nil失败。 失败的原因是,在multi或incr之前,我用另外一个客户端做了数据的变动。 你的事务提交给去后,redis会判断watch的那个key,有没有变动的。


加上watch key之后,是可以保证针对key的事物原子性。  multi exec和pipeline做都有一个批次的一次,但是他们之间又有什么区别?   

pipeline批量执行的时候,有可能是会被别的客户端打扰的。但是multi的话,他里面的逻辑是原子的,是一起执行的。

那么问题来了,有时候进行watch key,但有些场景我们需要一个互斥锁,redis实现锁还是比较容易的,有兴趣的朋友可以看看我以前的文章。 


http://xiaorui.cc/2014/12/19/python%E4%BD%BF%E7%94%A8redis%E5%AE%9E%E7%8E%B0%E5%8D%8F%E5%90%8C%E6%8E%A7%E5%88%B6%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/


另外这里提一下,用python实现watch multi的方式,代码如下.

python redis的模块封装的不错,里面带了一个pipe.reset(),意思就是重试,一直到watch的key不再被其他的客户端影响变化的时候,才break退出。 




对Python及运维开发感兴趣的朋友可以加QQ群 : 478476595 !!!
{ 2000人qq大群内有各厂大牛,常组织线上分享及沙龙,对高性能及分布式场景感兴趣同学欢迎加入该QQ群 }

另外如果大家觉得文章对你有些作用!   帮忙点击广告. 一来能刺激我写博客的欲望,二来好维护云主机的费用.
如果想赏钱,可以用微信扫描下面的二维码. 另外再次标注博客原地址  xiaorui.cc  ……   感谢!
暂无相关产品