起因是这样的,昨天突然发现以前用redis python的时候,从来没注意过他在多线程,多进程下fd复用的情况,直接都是公用一个连接对象。 

对比了多个好项目代码,貌似大家对mysql,mongodb十分的注意,都尽量不要让他有socket fd共享的情况,而对于redis的使用很是粗暴,直接共享。 

那么话说回来? 为什么要避免fd重用? 


该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新. http://xiaorui.cc/?p=3359

因为redis-py一直都没有报读写异常,我也就没有去测试和验证这个问题,就自以为是的觉得他在socket send or recv做了Lock,使command顺序化.  后来因为有个服务hbase thrift和elasticsearch连接出了问题,就遍历了父子进程的所有连接fd,惊奇的发现他们每个进程连接都不一样。 以前使用mysql的mysqldb模块,我们都是自己用lazy懒惰创建方法解决,而redis帮你实现了这么一个东西。 


注:

    可以发现在测试python脚本的结果里,4个子进程的local port都不一样的. 

对于我这么刨根问底的人来说,必须要搞清楚redis是怎么实现的每个进程用不同的连接的。 

redis-py的源代码地址, https://github.com/andymccurdy/redis-py , 作者andymccurdy是个很善于言谈的人,有兴趣的人可以看看youtube有关他的演讲视频,有些风趣. 

redis-py的一些设计巧妙,在该项目里还是可以借鉴一些优点的。 对于多进程连接共享问题你是如何解决的? 他们的实现很取巧 ,第一次初始化连接的时候会记录当前的pid。 当多个进程共用了这个连接去做command操作的时候,redis做了_checkpid()的动作? 这是什么意思? 如果当前的进程跟 第一次初始化的连接进程pid不一样的话,就重新创建一个redis连接。 

注: 我在自己的项目中用python也设计了一套类似redis python这样的connection管理类, 当然是管理MySQLdb的. 多进程下方法跟他类似,但多了单例模式这一步,在类变量里面初始化了pid — > connection. 
多线程下方法就跟他就不一样了,构建单例模式的时候,不仅会对进程pid判断,而且通过ctypes拿到threading id,对线程的id也会进行判断。 

下面是redis-py/connection.py 源码. 

令人尴尬的事情来了 !

到这里为止 redis python模块解决了多进程共用socket fd问题,但是我翻弄了redis-py的代码,没有看到redis-py对于多线程threading的处理.
我就fork了一个版本,提交了一段多线程下lazy mode的代码,逻辑是通过ctypes获取thread id,但是针对Class Connection加一层实例判断,测试通过后就提交了pull request merge请求。 

但提交了merge请求后,心有疑虑,作者连多进程的情况都考虑了,为什么不会考虑到多线程的场景? 不应该呀… 我后自己临时写了个脚本验证threading redis-py 共享连接问题… 验证的结果,每个线程都不同的连接…     果然呀,这20个线程都有自己的连接。  既然事情已经明了,没必要再去让别人merge代码了,带着羞愧,我把提交及fork都给删了。 太丢鸡了呀…. 


其实期初有关共享连接的问题,我给redis-py github提交过issue。  当然作者关注回复了我的问题,但回复内容只是不痛不痒的基础理论,估摸是自己的问题需求他没看懂。 

回到这个问题,redis-py是怎么解决这问题的。  就是这段代码,你可以照着redis-py反推,你会发现很多有趣的东西.  当你使用redis-py构建连接对象的时候,她不管你用不用Pool池,他都会给你实例化一个Pool池的,当然默认是给你一个只有一个连接的线程池。  他跟有max_connections的Pool区别在于, max_connections = max_connections or 2 ** 31

那么怎么关闭连接, del redis_conn_object

redis-py会主动回收redis连接么? 不会.  redis-py没有这段代码.  

andymccurdy的回答不是我想要的.  我想知道实现原理,这哥们跟我聊原理… 原理谁都知道…  


http://xiaorui.cc/?p=3359

END.



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

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

redis多线程服务端设计的一些思考

    最近有看redis server的源码,想实现一个多线程的版本。在大多数场景下单个redis实例是满足需求的,但如果ops的量级过十几万,连接数超过几k...

阅读全文

redis modules扩展模块的开发使用

上下文:       Redis 4.0 的RC终于出来了, 看了redis官方及antirez的博客都有提到4.0的各种新功能,对我来说是相当有吸引力的 。&n...

阅读全文

技术分享 《大话redis设计实现》

        这次又给朋友公司 (Naver) 做了一次技术分享,主题是《大话redis设计实现》 ,  里面的内容来自 学习《redis设计与实现》...

阅读全文