redis源码分析

主流程

server.c

全局变量server,只有一个,记录本服务的信息。
1.spt_init初始化全局环境变量,关联变量environ
2.设置时区
3.初始化oom_handler
4.其他初始化:随机数种子,crc64,acl,服务配置,tls,哨兵模式,帮助,加载配置文件,moduleInitModulesSystem模块系统初始化
5.关键函数initServer,初始化核心。
6.创建pid文件
7.设置cpu亲和性
8.执行事件循环核心
9.异常情况退出释放结束。

initServer

1.初始化处理信号的handlers
2.设置线程可以被kill
3.全局变量server初始化默认属性
4.创初始化共享对象shared
5.adjustOpenFilesLimit,根据配置判断文件描述符的数量限制
6.aeCreateEventLoop创建epoll循环对象
7.监听端口,设置非阻塞
8.aeCreateTimeEvent定时器初始化
9.设置accpet回调
10.aeCreateFileEvent使用管道初始化唤醒event loop的线程通信
11.设置sleep前后的回调函数
12.初始化集群clusterInit,副本集replicationScriptCacheInit,lua脚本scriptingInit,慢查询
slowlogInit,延迟监控latencyMonitorInit,acl默认密码ACLUpdateDefaultUserPassword。

redisSetCpuAffinity设置cpu亲和性

linux调用setcpuaffinity->sched_setaffinity,glibc的接口,最终调用系统调用INTERNAL_SYSCALL。

aeMain

aeApiPoll执行事件循环,linux一般使用epoll,epoll_wait阻塞。定时器事件processTimeEvents在最后处理。

reactor模型

ae_epoll

linux使用ae_epoll封装epoll。
ae.h声明了通用的事件函数,基本都是epoll的封装。
anet.h声明了tcp连接的操作函数。

connection

connection.h封装了连接的通用接口,最终会调用anet的tcp函数。
ConnectionType以函数指针的形式封装了接口,可以切换绑定的函数。

networking

networking.c主要是和客户端相关的连接操作。

rio

rio是文件相关操作的抽象封装。

syncio

同步读写操作接口。

集群

cluster

集群相关操作

replication

副本集相关操作

基础工具

crc64

crc64_init初始化,crc64计算校验值

pgsort,sort

排序算法,_pqsort高速排序算法。

sha1,sha256

哈希算法

压缩算法

lz算法

调试优化

debug

debug.c:重点关注logStackTrace和dumpCodeAroundEIP
logStackTrace:可通过信号,触发logStackTrace,核心原理是调用glibc的backtrace获取当前栈信息,backtrace_symbols_fd解析栈信息(查找符号表)到文件。
glibc通过elf库的_dl_addr获取详细信息解析。

dumpCodeAroundEIP:直接根据eip指针获得下一条指令的地址,然后通过dladdr能够得到dump信息。

memtest

内存测试

tracking

核心存储结构:使用基数树存储的TrackingTable和PrefixTable
客户端指令解析后,调用call的地方执行trackingRememberKeys,记录到TrackingTable
每个epoll循环的beforeSleep都会执行trackingBroadcastInvalidationMessages,发送tracking跟踪信息到客户端。

核心数据结构

redisServer

服务的全局信息,struct redisServer server;
包括pid,主线程id,配置文件路径,执行路径,参数,和其他客户端,连接,线程,备份,慢查询日志,oom_score,集群,scripts等等的配置和信息。

redisOp

定义了redis的操作,是解析客户端消息后的比较原始的结构数据

redisCommand

redisCommandTable数组:表驱动执行函数和命令信息。

redisDb

redis的db是字典查询的基本单位,需要指定db然后根据key查询字典找到对应的数据。

redisObject/robj

通用的redis数据结构封装,包含引用计数,获取和释放需要使用指定的函数。
incrRefCount/decrRefCount,引用计数为零,执行free

字典

所有redis数据类型的的存储都靠字典

rax基数树

 * This is the vanilla representation:
 *
 *              (f) ""
 *                \
 *                (o) "f"
 *                  \
 *                  (o) "fo"
 *                    \
 *                  [t   b] "foo"
 *                  /     \
 *         "foot" (e)     (a) "foob"
 *                /         \
 *      "foote" (r)         (r) "fooba"
 *              /             \
 *    "footer" []             [] "foobar"
 *

基数树层级固定了之后,最大时间复杂度就确定了,查询粒度小,速度快。

数据结构编码

编码属于redisObject的一个字段,占4位。
编码类型:

#define OBJ_ENCODING_RAW 0     /* Raw representation */
#define OBJ_ENCODING_INT 1     /* Encoded as integer */
#define OBJ_ENCODING_HT 2      /* Encoded as hash table */
#define OBJ_ENCODING_ZIPMAP 3  /* Encoded as zipmap */
#define OBJ_ENCODING_LINKEDLIST 4 /* No longer used: old list encoding. */
#define OBJ_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define OBJ_ENCODING_INTSET 6  /* Encoded as intset */
#define OBJ_ENCODING_SKIPLIST 7  /* Encoded as skiplist */
#define OBJ_ENCODING_EMBSTR 8  /* Embedded sds string encoding */
#define OBJ_ENCODING_QUICKLIST 9 /* Encoded as linked list of ziplists */
#define OBJ_ENCODING_STREAM 10 /* Encoded as a radix tree of listpacks */

持久化的时候需要用到。类型比较判断也需要用到。

其他功能

notify

rdb,aof,sentinel

redismodule

scripting

slowlog

布隆过滤器模块插件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值