- Redis的多路复用技术,支持epoll、kqueue、selector
- 5.0版本及以前,处理客户端请求的线程只有一个,串行处理
- 6.0版本引入了worker Thread,只处理网络IO读取和写入,核心IO负责串行处理客户端指令
就在 2019 年 12 月 20 号这天,众所期待的 Redis 新版 6.0 rc1 发布了(Redis 6 RC1 is out today)肯定很多关注的同学都进行了试用,虽然因为引入了 c11 的 _Atomic 导致相当多的环境都无法直接编译成功,但是对于想一探究竟的粉丝们来说,这是完全阻挡不了的热情
新版除了增加
ACLS 权限控制模块
、支持更为广泛的新协议 RESP3
、客户端缓存
、无磁盘同步
、Cluster Proxy
等十来个相当实用的新特性外,还对 长久以来 社区筒子们 呼声比较高的 多线程 进行了支持,当然也带来 性能提升了一倍 的好处这次我们的任务有两个:
剖析 Redis6 多线程的实现方式
与 Memcached 的多线程模型(个人认为这是一个极其经典的多线程网络编程案例)进行对比
众所周知,Redis 之前的版本一直都是典型的单线程模型(注意:这里不是指 Redis 单实例中只有一个线程,而是表示 核心操作模块由单线程完成,当然另外还有一些 辅助线程 从旁协助,比如 LRU 的淘汰过程
),为什么不使用多线程呢,其实原因很简单(官方解释)
简单说来就是:
- 根据以往的场景,普通 KV 存储 瓶颈压根不在 CPU,而往往可能受到
内存
和网络I/O
的制约 - Redis 中有各种类型的数据操作,甚至包括一些事务处理,如果采用多线程,则会被多线程产生的切换问题而困扰,也可能因为加锁导致系统架构变的异常复杂,更有可能会因为加锁解锁甚至死锁造成的性能损耗
当然,单线程也会有 不能充分利用多核资源 弊端,这是一个权衡;而通常 Redis(包括 Redis cluster) 的性能已经足够我们使用
那么,既然 单线程 都已经基本能满足场景,更不要说还能开启 多实例、上集群 等方式,那么为什么还要费力引入 多线程呢? 请继续阅读后方内容~~~
上面提到,瓶颈往往在 内存
和 网络I/O
内存方面毋容置疑,加就是了,虽然需要注意 NUMA陷阱(请自行 Googleÿ