Redis 6.0 为什么引入多线程?
Redis 基于内存操作,内存的响应时长大约为100纳秒,单线程的 Redis 处理数据的极限是 80,000 到 100,000 QPS,对于80%的公司来说,单线程的Redis已经足够使用了。
但随着硬件性能提升,Redis 的性能瓶颈可能出现⽹络 IO 的读写,也就是:单个线程处理⽹络读写的速度跟不上底层⽹络硬件的速度;越来越复杂的业务场景,也需要更大的QPS。
从 Redis 自身角度来说,因为读写网络的 read/write 系统调用占用了 Redis 执行期间大部分 CPU 时间,瓶颈主要在于网络的 IO 消耗, 优化主要有两个方向:
提⾼⽹络 IO 性能,典型的实现⽐如使⽤ DPDK 来替代内核⽹络栈的⽅式。
使⽤多线程充分利⽤多核,提⾼⽹络请求读写的并⾏度,典型的实现⽐如 Memcached 。
协议栈优化的这种方式跟 Redis 关系不大,支持多线程是一种最有效最便捷的操作方式。所以总结起来,redis支持多线程主要就是两个原因:
可以充分利用服务器 CPU 资源,目前主线程只能利用一个核。
多线程任务可以分摊 Redis 同步 IO 读写负荷。
Redis 的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程。之所以这么设计是不想因为多线程而变得复杂,需要去控制 key、lua、事务,LPUSH/LPOP 等等的并发问题。
4. Redis 6.0 的多线程模型
4.1 Redis 6.0 是否默认开启了多线程模型
否!Redis 6.0 的多线程是禁用的,默认使用是主线程。官方建议:只在机器至少有4个内核时才启用多线程模型,且至少留下一个备用内核。如果需要开启多线程需修改 redis.conf 配置文件:
# io-threads-do-reads no
# 改为
io-threads-do-reads yes
4.2 Redis 6.0 开启多线程后,如何设置线程数
开启多线程后,还需要设置线程数,否则是不生效的。同样修改redis.conf配置文件:
# io-threads 4
# 改为
io-threads 3
Redis 官方建议:只在机器至少有4个内核时才启用多线程模型,且至少留下一个备用内核。4核的机器建议设置为2或3个线程,8核的建议设置为6个线程,线程数一定要小于机器核数。还需要注意的是,线程数并不是越大越好,官方认为超过了8个基本就没什么意义了。
5. Redis多线程的实现机制
5.1 Redis 的多线程
Redis 采⽤多个 IO 线程来处理⽹络请求,提⾼⽹络请求处理的并⾏度。Redis 多 IO 线程模型只⽤来处理处理网络数据的读写和协议解析,对于 Redis 的读写命令,依然是单线程处理。这是因为:
⽹络处理经常是瓶颈,通过多线程并⾏处理可提⾼性能。
继续使⽤单线程执⾏读写命令,不需要为了保证 Lua 脚本、事务、等开发多线程安全机制,实现更简单。
架构图如下:
5.2 主线程与 IO 多线程是如何实现协作
Redis 6.0 多线程是把主线程处理网络IO和协议解析这两件事给了一组独立的线程处理,使得多个 socket 读写可以并⾏化,但 Redis 命令还是主线程串⾏执⾏。
主要流程如下:
主线程负责接收并建立(多个)连接请求,获取 socket 后放入全局等待处理队列;
主线程处理完这些事件之后,通过RR(Round Robin 轮询)将可读 socket 分配给这些 IO 线程;
主线程阻塞,等待 IO 线程完成命令的读取、解析;
主线程执⾏ IO 线程读取和解析出来的 Redis 请求命令,并将结果写到输出缓冲区;
主线程阻塞,等待 IO 线程将命令执⾏结果写回 socket(客户端);
主线程执行所有命令并清空整个等待队列,等待客户端后续的请求队列。
————————————————
原文链接:https://blog.csdn.net/weixin_42201180/article/details/128614691