134,735
社区成员
发帖
与我相关
我的任务
分享Redis在6.0之前是单线程模型,只需使用一个线程来通过事件循环来处理所有用户请求,就可以达到每秒数万 QPS 的处理能力。Redis 6.0发布了多线程模型,但这种多线程主要解决的就是网络 IO 部分(是接收请求参数、解析请求参数、响应 client ),处理命令接受和结果发送, 处理网络数据的读写和协议的解析, 对于命令的执行依然是单主线程在执行。这样设计可以大大提高IO性能,redis的瓶颈集中在内存和网络IP,多线程可有效提高并发能力,且保留的执行阶段的单线程又避免了多线程设计的线程频繁销毁创建和上线文切换问题,不用考虑并发资源竞争问题,从而总体上完成性能提升。但需要注意的是,在 redis6.0 中默认是不开启多线程,若要开启多线程,需要用户进行修改redis.conf 配置进行开启,如下所示
io-threads-do-reads yes
io-threads 20

redis 服务器启动时,创建一个线程池,线程个数最多128个。每个线程有一个队列。当主线程触发客户端请求事件到来时,把client对象中标志设置为CLIENT_PENDING_READ (说明需要读取请求),然后把触发的客户端加入到clients_pending_read 队里中,随后把该对列中client以轮训的方式分发给线程池中各自线程的队列中,主线程进入循环等待线程池处理请求完毕。各线程从自己的队里中取出分配的client对象,然后进行接收客户端发来的请求命令、解析命令,解析完后把client对象中标志设置为CLIENT_PENDING_COMMAND,说明命令已经解析完了。
主线程等待所有线程处理完后,根据 CLIENT_PENDING_COMMAND标志进行执行命令。命令执行完后,通过调用一组 addReplyXX 函数进行对客户端回应,先把 client 对象中标志设置为 CLIENT_PENDING_WRITE,然后把 client对象加入到全局队列 clients_pending_write 中。主线程把 clients_pending_write 对列中的client对象的以轮训的方式分发给线程池中各自线程的队列中,然后进入循环等待线程池处理完毕。线程池中的线程遍历各自的队列,把响应发送个客户端。主线程等待线程池中的线程处理全部处理完后,做后续其他处理。
该线程模型中属于生产者和消费者模型,主线程负责往线程池中发送消息,线程池中的线程进行消费。但该模型中并没有一般P/C模型中的加锁机制,这是因为线程池里的线程队列有计数器来完成队列的消费。