追求性能极致:Redis6.0的多线程模型

Redis系列1:深刻理解高性能Redis的本质Redis系列2:数据持久化提高可用性Redis系列3:高可用之主从架构Redis系列4:高可用之Sentinel(哨兵模式)Redis系列5:深入分析Cluster 集群模式
背景我们在第一篇《Redis系列1:深刻理解高性能Redis的本质》中就已经提到了,Redis 的网络 IO 以及键值对指令读写是由单个线程来执行的,避免了不必要的contextswitch和资源竞争,对于性能提升有很大的帮助 。而到了2020年的5月份,Redis官方 推出了 令人瞩目的 Redis 6.0,提出很多新特性,包含 多线程网络IO 的概念,如下:

追求性能极致:Redis6.0的多线程模型

文章插图
新特性内核优化应用优化其他ACL细粒度权限管控(包括ACL LOG)过期Key回收优化,增加配置参数新版本Module API全面支持SSL协议、并新增TSL协议客户端缓存(Client side caching)Resp3协议,兼容Resp2,更加简单、高效disque消息队列模块Redis-benchmark支持集群模式多线程处理网络 IO(Threaded I/O)优化了INFO命令,效率更高新增配置,支持Del命令如unlink执行Systemd支持重写Redis集群代理(Cluster proxy)优化阻塞命令,复杂度从O(n)到O(1)XINFO STREAM FULL流命令新增配置参数来删除用于在非持久性实例中进行复制的RDB文件支持linux/bsd系统的CPU和线程(包括子线程如aof、dbIO线程)亲和力绑定RDB加载速度优化CLIENT KILL USER username命令无磁盘复制副本(Diskless replication on replicas),从测试版优化,目前无磁盘复制在load rdb仍是测试版 。集群Slots命令优化Psync2优化,修复了5.0的链式复制不一致问题 。defrag优化,从试验版到正式版这其中比较引人注意的就是Threaded I/O和Client side caching这两项了 。这时候我们不免疑问,为什么6.0之前是单线程模式的,是基于什么考虑 。而现在为什么又要优化成 多线程网络IO模式,主要解决了哪些问题 ,带来了那些变化?这一篇咱们就详细就来聊下这个 Threaded I/O 。
6.0之前的单线程模式了解单线程模式之前,大家可以先回顾一下Redis系列第一篇 Redis系列1:深刻理解高性能Redis的本质。就会明白,Redis所谓的单线程并不是所有工作都是只有一个线程在执行,而是指Redis的网络IO和键值对读写是由一个线程来完成的,Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理 。这就是所谓的“单线程” 。这也是Redis对外提供键值存储服务的主要流程 。由于Redis在处理命令的时候是单线程作业的,所以会有一个Socket队列,每一个到达的服务端命令来了之后都不会马上被执行,而是进入队列,然后被线程的事件分发器逐个执行 。如下图:
追求性能极致:Redis6.0的多线程模型

文章插图
至于Redis的其他功能,比如持久化、异步删除、集群数据同步等等,其实是由额外的线程执行的 。可以这么说,Redis工作线程是单线程的 。但是在4.0之后,对于整个Redis服务来说,还是多线程运作的 。
那么问题来了,6.0之前为什么要使用单线程,通过 Redis官方的文档 ,我们看到他们有给出了说明:
追求性能极致:Redis6.0的多线程模型

文章插图