Redis6.0即将发布,比较吸引我的便是Redis6.0支持的多线程技术,Redis本身也并不是简单的单进程/线程模型,包括bgsave的进程以及对于一些慢请求的io线程(惰性删除,日志刷盘等),这次多线程的优化主要解决了Redis单进程/线程处理模型在协议解析以及网络IO上的消耗问题,在命令的处理上仍旧是单线程。
一、逻辑分析
2.1、两个配置
io-threads
:启用的IO的线程数,最大为128(老版本中配置判断为512,新版本已经修复统一为128);io-threads-do-reads
:是否启用IO多线程;
2.2、两个队列
clients_pending_read
:待处理的客户端的请求数据队列(需要进行协议解析等操作);clients_pending_write
:待处理的客户端的回复数据队列(需要进行回复客户端等操作);
2.3、两类线程
注意:启用的所有的多线程在同一时刻执行的任务类型是一样的
IO_THREADS_OP_WRITE
:执行clients_pending_read
任务的线程;IO_THREADS_OP_READ
:执行clients_pending_write
任务的线程;
2.4、多个函数
initThreadedIO
:初始化多线程,并将多线程置为停止状态;startThreadedIO
:启动多线程,并将io_threads_active
状态置为1
;stopThreadedIO
:停止多线程,并将io_threads_active
状态置为0
,需要处理多线程中未处理完成的任务;IOThreadMain
:多线程的执行函数,依据多线程的操作不同(IO_THREADS_OP_WRITE
/IO_THREADS_OP_READ
)执行对应的客户端的回复或者读取操作;handleClientsWithPendingWritesUsingThreads
:将clients_pending_write
队列中待处理的处理客户端的回复
分配给线程进行回复等操作;handleClientsWithPendingReadsUsingThreads
:将clients_pending_read
队列中待处理的客户端的请求
分配给处理线程进行协议解析等操作,然后执行相应的命令逻辑;afterSleep
:事件循环执行完成之后调用,函数内会调用handleClientsWithPendingReadsUsingThreads
函数;processCommandAndResetClient
:封装了processCommand
函数,增加多线程模型的情况的处理逻辑;postponeClientRead
:依据是否启动多线程,直接处理客户端的请求还是将请求添加到待处理队列clients_pending_read
中;stopThreadedIOIfNeeded
:如果clients_pending_write
较小,即客户端数量较少时自动停止多线程;