【专栏简介】
随着数据需求的迅猛增长,持久化和数据查询技术的重要性日益凸显。关系型数据库已不再是唯一选择,数据的处理方式正变得日益多样化。在众多新兴的解决方案与工具中,Redis凭借其独特的优势脱颖而出。
【技术大纲】
为何Redis备受瞩目?原因在于其学习曲线平缓,短时间内便能对Redis有初步了解。同时,Redis在处理特定问题时展现出卓越的通用性,专注于其擅长的领域。深入了解Redis后,您将能够明确哪些任务适合由Redis承担,哪些则不适宜。这一经验对开发人员来说是一笔宝贵的财富。
在这个专栏中,我们将专注于Redis的6.2版本进行深入分析和介绍。Redis 6.2不仅是我个人特别偏爱的一个版本,而且在实际应用中也被广泛认为是稳定性和性能表现都相当出色的版本。
【专栏目标】
本专栏深入浅出地传授Redis的基础知识,旨在助力读者掌握其核心概念与技能。深入剖析了Redis的大多数功能以及全部多机功能的实现原理,详细展示了这些功能的核心数据结构和关键算法思想。读者将能够快速且有效地理解Redis的内部构造和运作机制,这些知识将助力读者更好地运用Redis,提升其使用效率。
将聚焦于Redis的五大数据结构,深入剖析各种数据建模方法,并分享关键的管理细节与调试技巧。
【目标人群】
Redis技术进阶之路专栏:目标人群与受众对象,对于希望深入了解Redis实现原理底层细节的人群。
1. Redis爱好者与社区成员
Redis技术有浓厚兴趣,经常参与社区讨论,希望深入研究Redis内部机制、性能优化和扩展性的读者。
2. 后端开发和系统架构师
在日常工作中经常使用Redis作为数据存储和缓存工具,他们在项目中需要利用Redis进行数据存储、缓存、消息队列等操作时,此专栏将为他们提供有力的技术支撑。
3. 计算机专业的本科生及研究生
对于学习计算机科学、软件工程、数据分析等相关专业的在校学生,以及对Redis技术感兴趣的教育工作者,此专栏可以作为他们的学习资料和教学参考。
无论是初学者还是资深专家,无论是从业者还是学生,只要对Redis技术感兴趣并希望深入了解其原理和实践,都是此专栏的目标人群和受众对象。
让我们携手踏上学习Redis的旅程,探索其无尽的可能性!
初始化服务器
Redis服务器自启动至具备处理客户端命令请求的能力,需经历一系列严谨的初始化与配置环节。
其中涵盖了初始化服务器运行状态 、加载用户设定 的配置参数、构建必要的数据结构体系 以及建立网络通信连接 等关键步骤。接下来,将对Redis服务器完整的初始化流程展开细致阐述。
1. 初始化服务器状态结构
初始化服务器的第一步就是创建一个结构体structredisServer
类型的实例变量作为服务器的状态,并为结构中的各个属性设置默认值。
初始化RedisServer
变量
初始化RedisServer
变量的工作由redis.c/initServerConfig
函数完成,以下是这个函数最开头的一部分代码:
c
void initserverConfig(void){
//设置服务器的运行id
getRandomHexChars(server.runid,REDIS_RUN_ID_SIZE)
//为运行id加上结尾字符
server.runid[REDIS_RUN_ID_SIZE] = '\0';
//设置默认配置文件路径
server.configfile = NULL;
//设置默认服务器频串
server.hz = REDIS_DEFAULT_HZ;
//设置服务器的运行架构
server.arch_bits = (sizeof (long) == 8 )64 32;
//设置默认服务器端口号
server.port = REDIS_SERVERPORT;
}
以下是initServerConfig
函数完成的主要工作:
注意,
initServerConfig
函数没有创建服务器状态的其他数据结构,数据库、慢查询日志、Lua环境、共享对象这些数据结构在之后的步骤才会被创建出来。
当initServerConfig
函数执行完毕之后,服务器就可以进人初始化的第二个阶段一载人配置选项。
2. 加载相关系统配置和用户配置参数
在启动服务器时,用户可以通过给定配置参数或者指定配置文件来修改服务器的默认配置。举个例子,如果我们在终端中输人
定制化配置参数
bash
$ \redis-server --port 6387
那么我们就通过给定配置参数的方式,修改了服务器的运行端口号。另外,如果我们在终端中输人:
bash
$ \redis-server redis.conf
并且redis.conf文件中包含以下内容:
shell
#将服务器的数据库数量设置为32个
databases 32
#关闭RDB文件的压缩功能
rdbcompression no
那么我们就通过指定配置文件的方式修改了服务器的数据库数量,以及RDB
持久化模块的压缩功能。
服务器在用initServerConfig
函数初始化完server变量之后,就会开始载人用户给定的配置参数和配置文件,并根据用户设定的配置,对server变量相关属性的值进行修改。
案例分析
例如,在初始化server变量时,程序会为决定服务器端口号的port属性设置默认值:
c
void initServerconfig(void){
//默认值为6379
server.port=REDIS_SERVERPORT;
}
更新服务端口号
如果用户在启动服务器时为配置选项port指定了新值6378($ redis-server --port 6378
),那么server. port
属性的值就会被更新为6378
,这将使得服务器的端口号从默认的6379变为用户指定的6378。
更新数据库个数
如果用户在启动服务器时为选项databases
设置了值32
,那么server. dbnum
属性的值就会被更新为32,这将使得服务器的数据库数量从默认的16个变为用户指定的32个。
配置覆盖总结

服务器在载入用户指定的配置选项,并对server状态进行更新之后,服务器就可以进人初始化的第三个阶段一初始化服务器数据结构。
3. 创建和初始化对应的对象结构实例
在之前执行initServerConfig
函数初始化server状态时,程序只创建了命令表一个数据结构,不过除了命令表之外,服务器状态还包含其他数据结构,比如:
server.clients
(链表):记录了与服务器相连的客户端的状态结构,每个节点包含redisclient结构实例server.db
(数组):包含了服务器的所有数据库。server.pubsub channels
(字典):保存频道订阅信息,以及保存模式订阅信息的server,pubsub_patterns
链表。server.lua
:执行Lua 脚本的Lua环境server.slowlog
:慢查询日志的属性
initServer初始化服务器
初始化服务器 进行到这一步,服务器将调用initServer
函数,为以上提到的数据结构分配内存,并在有需要时,为这些数据结构设置或者关联初始化值。
注意,服务器到现在才初始化数据结构的原因在于,服务器必须先载入用户指定的配置选项,然后才能正确地对数据结构进行初始化。
创建和修改内存数据结构
如果在执行initServerConfig
函数时就对数据结构进行初始化,那么一旦用户通过配置选项修改了和数据结构有关的服务器状态属性,服务器就要重新调整和修改已创建的数据结构。
为了避免出现这种麻烦的情况,服务器选择了将server状态的初始化分为两步进行:
initServerConfig
函数主要负责初始化属性initserver
函数主要负责初始化数据结构
initServer分配内存对象
- 创建进程信号处理器
- 创建共享复用对象
- Redis服务器常用的值,像表示 "OK" 回复、"ERR" 回复的字符串对象,以及对应整数1到10000的字符串对象等。服务器复用这些共享对象,避免重复创建相同对象。
- 创建事件监听器
- 监听套接字关联连接应答事件处理器,待服务器正式运行时接收客户端连接。
- 创建时间事件
- 同时为
serverCron
函数创建时间事件,待服务器运行时执行该函数。
- 同时为
- 载入AOF文件数据
- 若AOF持久化功能已开启,打开现有的AOF文件;若文件不存在,则创建并打开新的 AOF 文件,为 AOF 写入操作做准备。
- 建立I/O处理器模块 :
- 初始化服务器的后台I/O模块,为后续的 I/O 操作做好准备。
总结介绍
serverCron
函数默认每隔100毫秒执行一次,它的工作主要包括更新服务器状态信息,处理服务器接收的SIGTERM
信号,管理客户端资源和数据库状态,检查并执行持久化操作等等。
命令请求从发送到完成主要包括以下步骤:

服务从启动到能够处理客户端的求需要执行以下步骤:

载入RDB文件或者AOF文件
服务器依据文件记录还原数据库状态,具体方式取决于AOF持久化功能是否启用:若启用,使用AOF文件还原;若未启用,则使用RDB文件。完成数据库状态还原后,服务器会在日志中记录文件载入及状态还原耗时。