【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

【专栏简介】

随着数据需求的迅猛增长,持久化和数据查询技术的重要性日益凸显。关系型数据库已不再是唯一选择,数据的处理方式正变得日益多样化。在众多新兴的解决方案与工具中,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文件。完成数据库状态还原后,服务器会在日志中记录文件载入及状态还原耗时。

相关推荐
wuxuanok4 分钟前
Web后端开发-分层解耦
java·笔记·后端·学习
周胡杰20 分钟前
鸿蒙arkts使用关系型数据库,使用DB Browser for SQLite连接和查看数据库数据?使用TaskPool进行频繁数据库操作
前端·数据库·华为·harmonyos·鸿蒙·鸿蒙系统
315356691321 分钟前
ClipReader:一个剪贴板英语单词阅读器
前端·后端
wkj00124 分钟前
navicate如何设置数据库引擎
数据库·mysql
ladymorgana24 分钟前
【Spring Boot】HikariCP 连接池 YAML 配置详解
spring boot·后端·mysql·连接池·hikaricp
赵渝强老师26 分钟前
【赵渝强老师】Oracle RMAN的目录数据库
数据库·oracle
暖暖木头28 分钟前
Oracle注释详解
数据库·oracle
neoooo1 小时前
别慌,Java只有值传递——一次搞懂“为啥我改了它还不变”!
java·后端·spring
御控工业物联网1 小时前
御控网关如何实现MQTT、MODBUS、OPCUA、SQL、HTTP之间协议转换
数据库·sql·http
用户7785371836961 小时前
一力破万法:从0实现一个http代理池
后端·爬虫