Redis 线程模型
背景
随着年龄的增长,很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来,技术出身的人总是很难放下一些执念,遂将这些知识整理成文,以纪念曾经努力学习奋斗的日子。本文内容并非完全原创,大多是参考其他文章资料整理所得,感谢每位技术人的开源精神。
简介
本文介绍 Redis 线程模型的原理及演进,主要介绍 Redis 核心网络模型。
Redis 单线程
早期的 Redis 版本(准确点说是 Redis v4.0 之前的版本)使用的是单线程模型,Redis 官方给出的解释是:Redis 的瓶颈通常不会是 CPU,因为大多数请求都是 I/O 密集型而非 CPU 密集型,如果不考虑 RDB/AOF 等持久化方案,Redis 是完全的纯内存操作,执行速度非常快。Redis 真正的性能瓶颈在网络 I/O,也就是客户端与服务器之间的网络传输延迟。除此之外,单线程也可避免过多的上下文切换开销及线程同步机制开销,对 Redis 的设计、开发及维护也更加简单。
Redis v6.0 版本之前,核心网络模型一直是一个典型的 单 Reactor 模型,利用 select / epoll / kqueue 等 I/O 多路复用技术,在单线程事件循环中不断去处理客户端请求事件,最后回写响应数据到客户端。
核心概念:
client
:客户端对象,Redis 是典型的 CS 架构(Client - Server),客户端通过 Socket 与服务器建立连接并发送请求命令,服务器执行请求的命令并回写响应。Redis 使用结构体client
存储客户端所有相关信息,包括套接字连接(*conn
)、当前选择的数据库指针(*db
)、读入缓冲区(querybuf
)、写出缓冲区(buf
)、写出数据链表(reply
)等。aeApiPoll
:I/O 多路复用 API,是基于 select / epoll_wait / kevent 等系统调用的封装,监听等待读写事件触发,然后处理,它是事件循环(Event Loop)中的核心函数,是事件驱动得以运行的基础。acceptTcpHandler
:连接应答处理器,底层使用系统调用accept
接受来自客户端的新连接,并为新连接注册绑定命令读取处理器,以备后续处理新的客户端 TCP 连接;除了这个处理器,还有对应的acceptUnixHandler
负责处理 Unix Domain Socket 以及acceptTLSHandler
负责处理 TLS 加密连接。readQueryFromClient
:命令读取