Redis本质上是一个数据结构服务器,支持键值对类型存储的内存管理系统,可以用作数据库、缓存和消息中间件,在我日常的开发中,基本上使用redis作为缓存中间件。
在Redis中有两个重要的角色,一个是服务器server,一个是客户端client,他们是一对多的关系,服务器会保存每个与之相连接的客户端的状态信息。本文会从这两个角色,分析客户端和服务器中一些比较重要的属性结构,以及一个命令从客户端发送到服务器接受、处理并返回的实现原理。
1.Server服务器
Redis服务器启动后,需要经过一些列的初始化及配置的设置,之后就可以接收客户端的命令请求,进行相关操作了,那么服务器初始化的整个过程,主要包含以下几步
- 初始化服务器的状态参数:这里主要是创建redisServer这个结构体的实例变量server,并为server中的属性赋值,以存储服务器的状态,但是这里设置的都是一些简单的整数或者字符串等等,比如服务器的运行id,端口号,持久化的触发条件等等,较为复杂的结构不会在这里设置,这一步通过 initServerConfig函数处理。
- 载入用户配置项:这一步会载入用户通过命令参数或者配置文件设置的服务器状态信息,对server变量中的相关属性进行修改。
- 初始化服务器数据结构:这一步会执行除第一步之外相对复杂的数据结构,如server.clients链表、db数组、server.lua客户端等等,之所以与第一步分开,是因为这一步的结构体的创建可能与第二步用户配置的参数有关,这一步会通过initServer函数处理。经过此步之后,会执行两个重要的步骤,一是服务端创建监听套接字,并关联应答事件处理器,等待客户端的连接;二是开始执行serverCron这个时间事件函数。
- 还原数据库状态:载入AOF或者RDB持久化的目标文件,如果AOF持久化开启,服务器使用AOF文件还原数据库的状态,否则使用RDB的持久化文件还原。
- 执行事件循环:这里是开始执行主函数中的文件事件和时间事件函数。redis主函数一旦开始执行后,会找要最近一次需要执行的时间事件,计算当前时间与这个时间事件的时差,在这个时间段内会阻塞等待文件事件,并关联事件处理器去处理,由于命令函数处理时间长短无法确定,所以时间事件的实际处理时间,通常会比它本身设定的执行时间会稍微晚一些。
2.Client客户端
2.1 客户端创建
客户端首次创建,连接到服务器之后,会向服务器发送命令,并得到相应的结果和回复。在redis中,客户端可以分为三种类型:一种是负责执行Lua脚本的伪客户端,一种是用来加载aof文件的伪客户端,还有一种就是通过网络连接的普通客户端。
对于通过网络与redis服务器连接的普通客户端和lua脚本的客户端,服务器都会