Redis网络模型与通信协议

Redis网络模型与通信协议

网络模型

Redis到底是单线程还是多线程?

  • 如果仅仅聊Redis的核心业务部分(命令处理),答案是单线程

  • 如果是聊整个Redis,那么答案就是多线程

在Redis版本迭代过程中,在两个重要的时间节点上引入了多线程的支持:

  • Redis v4.0:引入多线程异步处理一些耗时较旧的任务,例如异步删除命令unlink

  • Redis v6.0:在核心网络模型中引入多线程,进一步提高对于多核CPU的利用率

因此,对于Redis的核心网络模型,在Redis 6.0之前确实都是单线程,是利用epoll这样的IO多路复用技术在事件循环中不断处理客户端情况。

为什么Redis要选择单线程?

  • 抛开持久化不谈,Redis是纯内存操作,执行速度非常快,它的性能瓶颈是网络延迟而不是执行速度,因此多线程并不会带来巨大的性能提升。
  • 多线程会导致过多的上下文切换,带来不必要的开销。
  • 引入多线程会面临线程安全问题,必然要引入线程锁这样的安全手段,实现复杂度增高,而且性能也会大打折扣。

Redis通过IO多路复用来提高网络性能,并且支持各种不同的多路复用实现,并且将这些实现进行封装,提供了统一的高性能事件库API库 AE:

image-20240303110050282

Redis单线程网络模型的流程:

image-20240303110205714

image-20240303110240412

image-20240303110603258

image-20240303110742944

image-20240303111512660

Redis多线程网络模型的流程:

Redis网络模型整体就是一个IO多路复用+事件派发的结构,通过epoll_create创建一个epoll对象(包含监听FD的红黑树和就绪FD链表),将ServerSocket的FP通过epoll_ctl注册到epoll对象上监听读事件,然后调用epoll_wait等待就绪FD列表,在遍历就绪FD列表中1.如果发现FD是ServerSocket则派发给连接应答处理器tcpAcceptHandler(调用accept函数获得客户端socket并注册到epoll对象上监听读事件),2.如果发现是ClientSocket则根据事件类型派发:2.1读事件则派发给命令请求处理器readQueryFromClient,完成请求数据的解析和命令处理;2.2写事件则派发给命令回复处理器sendReplyToClient完成响应数据的写回。

image-20240303110627676

通信协议

image-20240303111542285

image-20240303112025131