前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redis代码走读与编程实践——网络交互篇(上)

redis代码走读与编程实践——网络交互篇(上)

原创
作者头像
王鹏程1990
修改2021-06-19 18:59:53
8210
修改2021-06-19 18:59:53
举报
文章被收录于专栏:源码阅读

导语

redis是一种内存数据存储系统,可被用作数据库、缓存、消息队列等;以高性能、高并发能力著称;本文分为上下两篇,其中上篇主要着眼于最简单的单机数据库&非事务命令场景,对网络框架相关代码进行走读,阐述redis服务器如何接收来自客户端的连接请求,建立连接并与响应客户端的指令,找到对应的处理代码;下篇主要是尝试编写简单的redis客户端,从最简单的建立连接开始,到和redis-server进行交互,借此加深对上篇阅读代码的理解,并在最后模仿redis-server的连接管理模型,实现一个简单的server demo。更多内容移步作者个人博客

概述

redis是基于事件驱动的单线程应用;事件收集器收集事件(这里主要是网络事件和定时事件)之后,分发到各个模块进行处理(在redis中是找到对应事件的注册回调函数);如下图所示:

配置相关

本文主要关注于网络事件模块的代码走读,为便于分析,会略过无关的代码和配置。

1. 服务端相关配置

因为后续需要通过修改相关的redis配置信息来配合一些实验,所以先介绍redis相关的一些配置信息:

a) redis通过启动命令redis-server [conf-file-path]命令指定配置文件

b) 若是不指定,则默认使用同目录下redis.conf文件作为配置文件

Redis.conf中和网络相关的配置包括:

a) port:指定监听端口号

b) bind: bind用于配置redis进程监听的IP地址;若是没有配置的话,redis进程会监听机器上的所有的IP

c) protected-mode no/yes: 配置保护模式是否开启

  1. 保护模式是redis的一个安全措施,用于避免redis被暴露到外网
  2. 保护模式开启,则只有本机的客户端可以连接到redis的服务进程
  3. 为使得redis服务可以被其他机器访问,需要关闭保护模式&bind非回环地址(现网场景下,需要配置密码requirepass)

d) timeout::配置client闲置多少秒之后,断开链接;0表示不启用, 为便于调试,实验环境我们不启用这个机制

e) logfile/loglevel: 配置日志文件的路径和等级

f) Maxclients: 表示redis服务器端,能接收的最大链接数

g) requirepass: 配置redis服务的密码

启动阶段

redis-server的网络模块在启动过程中主要完成两块工作:

  1. 解析配置文件和命令行参数,完成初始化工作;
  2. 根据配置信息,创建要监听的socket,并注册回调;

下面依次进行论述。

启动阶段

redis-server的网络模块在启动过程中主要完成两块工作:

l 解析配置文件和命令行参数,完成初始化工作;

l 根据配置信息,创建要监听的socket,并注册回调;

下面依次进行论述。

a) 解析配置及初始化

如代码所示

  1. 接口loadServerConfig,接收命令行参数,其中filename指定了配置的文件名;而options则指定了其他配置参数;最终都被存放到config数组中,传入到接口loadServerConfigFromString进行解析
  2. 接口loadServerConfigFromString,对字符数组进行按照\t\r\n进行分割;并且对于空串”\0”和”\#”不进行处理
  3. 所有的配置,都被解析,存放在类型为redisServer的全局变量server中;具体可参照源码,不再赘述

b) 创建监听socket并注册事件回调

所有配置信息都被读入到server结构体之后,接口initServer开始创建监听socket并注册回调,代码如下所示:

主要做了以下工作:

  1. l结构体aeEventLoop事件收集器
  2. 接口aeCreateEventLoop通过接口aeApiCreate创建一个epoll实例
  3. 接口listenToPort绑定所有IP上对应的端口,
  4. 通过接口aeCreateFileEvent注册监听的socket句柄,及对应的回调函数acceptTcpHandler

客户端连接建立阶段

连接建立请求检测轮询接口
连接建立请求检测轮询接口
连接建立请求接口
连接建立请求接口

主要流程包括:

  1. 客户端请求建立连接触发监听接口读事件,从而触发回调acceptTcpHandler
  2. acceptTcpHandler调用接口anetTcpAccept来接收连接,分配对应socket
  3. 连接建立之后,通过acceptCommonHandler,创建描述客户端的类型为client结构体&注册事件监听和回调,并通过全局变量server的client链表管理所有的客户端
  4. 此外接口acceptCommonHandler还进行最大连接数检查(客户端连接数是否大于server.maxclients)和保护模式下检查(保护模式下未配置密码只允许本地访问),检查通过则连接正式建立

交互流程

redis客户端和服务器建立连接之后,即可以通过客户端向redis-server发送命令;执行流程如下所述:

客户端输入指令的主调接口
客户端输入指令的主调接口
指令解析接口
指令解析接口

主流程如下:

  1. 主循环通过接口aeProcessEvents收集已经有客户端数据上来的socket
  2. 对于有数据的socket,触发回调readQueryFromClient,读入客户端请求
  3. 针对非管道指令,通过调用链processInputBuffer->processMultibulkBuffer对请求的参数进行解析(同时校验请求的合法性,参数合法性、参数个数合法性、长度合法性等),解析的结果存放在client->argv和client->argc中
  4. 解析出客户端请求的各个字段之后,通过processCommand这个接口找到对应的命令结构体,执行其对应的回调

以上为redis网络交互模块,监听接口注册、连接建立、注册回调以及命令解析与交互的主要流程源码走读;因笔者能力有限,若有疏误欢迎留言指正;

参考资料

1. https://redis.io/

2. https://www.xilidou.com/2018/03/22/redis-event/

3. https://www.runoob.com/redis/redis-pipelining.html

4. https://cloud.tencent.com/developer/article/1005481

5. http://blog.chinaunix.net/uid-28541347-id-4238524.html

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导语
  • 概述
  • 配置相关
  • 启动阶段
  • 启动阶段
  • 客户端连接建立阶段
  • 交互流程
  • 参考资料
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档