Redis 6 的多线程

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 昨天和同事聊Redis,他问我Redis学的怎么样,我说学的还行,然后他突然问一句“你知道Redis现在已经支持多线程了吗?”,我当时愣了一下,Redis不是一直是单线程么,怎么突然支持多线程了?瞬间感觉被秒,赶紧回来查阅一下相关资料,要不然以后都不敢说自己会Redis了

 昨天和同事聊Redis,他问我Redis学的怎么样,我说学的还行,然后他突然问一句“你知道Redis现在已经支持多线程了吗?”,我当时愣了一下,Redis不是一直是单线程么,怎么突然支持多线程了?瞬间感觉被秒,赶紧回来查阅一下相关资料,要不然以后都不敢说自己会Redis了


1. Redis知识回顾


我们先回顾一下Redis单线程模式的相关知识,我们都知道Redis快的主要原因是因为epool I/O复用模型,我们简单探讨一下:

  • 首先,Redis 是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或输出都是阻塞的,所以 I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O 阻塞导致整个进程无法对其它客户提供服务,而 I/O 多路复用就是为了解决这个问题而出现的。
  • 多路I/O复用模型是利用 select、poll、epoll 可以同时监听多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
  • 这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量

下图是Redis的内部核心流程图(也是我能找到的比较经典的介绍Redis的原理图),内部其实主要是通过双向队列和红黑树实现(图画的很详细,里面不懂的知识,可以直接百度,很容易找到)

ND]}F4U~`C`V54L5ITBM@6Q.png


2. Redis单线程


对于一个请求操作,Redis主要做3件事情:从客户端读取数据、执行Redis命令、回写数据给客户端(如果再准确点,其实还包括对协议的解析)。所以主线程其实就是把所有操作的这3件事情,串行一起执行,因为是基于内存,所以执行速度非常快

SRW$OURB__)DZS5DMP)TY6X.png

优点 VS 缺点:
优势:a. 不存在锁的问题b. 避免线程间CPU切换缺点:a. 单线程无法利用多CPUb. 串行操作,某个操作“出问题”会“阻塞”后续操作


3. Redis多线程


Redis多线程的优化思路:因为网络I/O在Redis执行期间占用了大部分CPU时间,所以把网络I/O部分单独抽离出来,做成多线程的方式。这里所说的多线程,其实就是将Redis单线程中做的这两件事情“从客户端读取数据、回写数据给客户端”(也可以称为网络I/O),处理成多线程的方式,但是“执行Redis命令”还是在主线程中串行执行,这个逻辑保持不变。

B~9(Z9_6IHP$YF[)OE(A6]P.png

可能有同学会问,主线程和多个I/O线程,都同时处理图中的“队列”,是不是会存在锁竞争的关系呢?这里有个巧妙的设计,就是当epoll获取socket链接时,会将该事件先全部扔进队列中,比如扔了N个事件,这时主线程就会处于忙等(spinlock自旋锁的效果)状态。然后多个I/O线程开始去并行进行网络I/O,并对数据进行协议解析,当队列全部处理完毕后,主线程会对队列中请求串行“执行Redis命令”,然后清空该队列。所以整个执行流程总结下来:主线程执行请求入队列 -> I/O线程并行进行网络读 -> 主线程串行执行Redis命令 -> I/O线程并行进行网络写 -> 主线程清空队列,并接收下一批请求。优点 VS 缺点

优点:a. 提高响应速度,充分使用CPU

缺点:a. 增加了代码复杂性


4. 总结


  • Redis的多路复用技术,支持epoll、kqueue、selector;
  • 5.0版本及以前,处理客户端请求的线程只有一个,串行处理;
  • 6.0版本引入了worker Thread,只处理网络IO读取和写入,核心IO负责串行处理客户端指令。
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
3月前
|
监控 NoSQL 安全
如何在 Redis 中正确使用多线程?
【10月更文挑战第16天】正确使用 Redis 多线程需要综合考虑多个因素,并且需要在实践中不断摸索和总结经验。通过合理的配置和运用,多线程可以为 Redis 带来性能上的提升,同时也要注意避免可能出现的问题,以保障系统的稳定和可靠运行。
68 2
|
3月前
|
存储 NoSQL Redis
Redis 新版本引入多线程的利弊分析
【10月更文挑战第16天】Redis 新版本引入多线程是一个具有挑战性和机遇的改变。虽然多线程带来了一些潜在的问题和挑战,但也为 Redis 提供了进一步提升性能和扩展能力的可能性。在实际应用中,我们需要根据具体的需求和场景,综合评估多线程的利弊,谨慎地选择和使用 Redis 的新版本。同时,Redis 开发者也需要不断努力,优化和完善多线程机制,以提供更加稳定、高效和可靠的 Redis 服务。
71 1
|
10天前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
34 1
|
4月前
|
消息中间件 存储 NoSQL
剖析 Redis List 消息队列的三种消费线程模型
Redis 列表(List)是一种简单的字符串列表,它的底层实现是一个双向链表。 生产环境,很多公司都将 Redis 列表应用于轻量级消息队列 。这篇文章,我们聊聊如何使用 List 命令实现消息队列的功能以及剖析消费者线程模型 。
109 20
剖析 Redis List 消息队列的三种消费线程模型
|
3月前
|
存储 运维 NoSQL
Redis为什么最开始被设计成单线程而不是多线程
总之,Redis采用单线程设计是基于对系统特性的深刻洞察和权衡的结果。这种设计不仅保持了Redis的高性能,还确保了其代码的简洁性、可维护性以及部署的便捷性,使之成为众多应用场景下的首选数据存储解决方案。
46 1
|
3月前
|
NoSQL Redis 数据库
Redis单线程模型 redis 为什么是单线程?为什么 redis 单线程效率还能那么高,速度还能特别快
本文解释了Redis为什么采用单线程模型,以及为什么Redis单线程模型的效率和速度依然可以非常高,主要原因包括Redis操作主要访问内存、核心操作简单、单线程避免了线程竞争开销,以及使用了IO多路复用机制epoll。
62 0
Redis单线程模型 redis 为什么是单线程?为什么 redis 单线程效率还能那么高,速度还能特别快
|
4月前
|
NoSQL 网络协议 Unix
1)Redis 属于单线程还是多线程?不同版本之间有什么区别?
1)Redis 属于单线程还是多线程?不同版本之间有什么区别?
100 1
|
4月前
|
存储 消息中间件 NoSQL
Redis的单线程设计之谜:高性能与简洁并存
Redis的单线程设计之谜:高性能与简洁并存
51 1
|
缓存 NoSQL JavaScript
Redis之线程IO模型
Redis之线程IO模型
609 0
|
13天前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
155 85