当多线程的数据库使用了为单线程设计的协议……

作者: yangzhe1991 分类: 我是搞技术的 发布时间: 2015-05-22 22:44 ė 63条评论

因为redis是单线程,请求都是串行,所以协议的设计很简单(陋),client也假定数据库是单线程所以也比较简单,比如有了pipeline后完全没有搞异步接口的必要,其他语言不知道,Java的jedis应该是没有的,全是同步阻塞的。

但一旦扩展成多线程,比如codis,一个client在一个业务逻辑内一次读多个key,在基于当前的redis client的接口的情况下,因为协议串行导致必须按顺序返回给客户端,又因为proxy的下层是多个slot、多个redis,不能用pipeline,所以按照目前的实现,client直接mget多个key,或者pipeline连某个proxy,只能串行分发到下面处理,网络ping-pong的次数显著增加,很可能会导致反而比单redis还慢。当然,redis官方的cluster,直接把pipeline屏蔽掉了,因为要直接在client算slot请求对应节点。

所以只要client没有自行搞出异步的接口,无论codis还是官方cluster在同时请求多个key的时候都是个悲剧。对codis来说,目前的解决方案只能是自行搞异步接口,请求N个key由client分在M个connection去请求,M越多甚至可能M=N时最快,但client就需要开很多个connection了。

如果改codis的proxy,也是可以搞的。最简单的实现方式就是每个connection的每个请求无视顺序都发给redis,同时搞个list存每个请求的WaitGroup,时刻阻塞等待链表头的wg,保证回复response时按照request的顺序,只要下一个请求没返回也没超时就一直等着。这里改成纯异步的之后,用mget和pipeline的性能会好不少甚至可能因为多个redis而远超单机性能。不过一些一致性的问题可能也需要考虑,比如pipeline纯异步后一旦中间某个请求挂了,后面是无法不执行的,需要用户承受这一点。

 

本文出自 杨肉的演讲台,转载时请注明出处及相应链接。

本文永久链接: https://yangzhe1991.org/blog/2015/05/codis-async/

3条评论

  1. 1 2015 年 6 月 1 日 11:28 回复
    Unknown Unknown Unknown Unknown

    3

    1. 1 2015 年 6 月 1 日 11:29 回复
      Google Chrome 43.0.2357.81 Google Chrome 43.0.2357.81 Mac OS X  10.10.3 Mac OS X 10.10.3

      alert(1)

  2. 打杂 2016 年 6 月 3 日 11:53 回复
    Firefox 46.0 Firefox 46.0 Windows 8.1 x64 Edition Windows 8.1 x64 Edition

    多线程有多线程的好,
    单线程有单线程的好,
    对于一个内存数据库来说,其实,单线程比多线程要好,
    内存访问的数据太快了,
    内网网络那么快,多线程访问对内存数据库来说,压力有点大。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Ɣ回顶部