# redis **Repository Path**: wfusu/redis ## Basic Information - **Project Name**: redis - **Description**: redis 源码学习 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2017-07-19 - **Last Updated**: 2020-12-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # redis 源码学习 redis v5.0.4 ## new feature ### Stream数据结构 ### 内存使用优化 Redis5.0在上一版本基础上,在内存使用上做了进一步优化。 - 主动碎片整理 当key被频繁修改,value长度不断变化时,Redis会为key分配新的内存空间。由于Redis追求高性能,实现了自己的内存分配器来管理内存,因此并不会将原有内存释放给OS,从而导致出现内存碎片。当used_memory_rss/used_memory高于1.5,一般认为内存碎片占比过高,内存利用率低。 因此,合理规划和使用缓存数据,规范数据写入,有助于减少内存碎片的产生。 Redis3.0及以下:可以通过定期重启服务解决内存碎片问题。建议实际缓存数据不超过配置可用内存的50%。 Redis4.0:支持主动整理内存碎片,服务在运行期间进行自动内存碎片清理。同时Redis4.0支持通过memory purge命令手动清理内存碎片。 Redis5.0:增强版主动碎片整理,配合Jemalloc版本更新,更快更智能,延时更低。 - HyperLogLog算法优化 HyperLogLog是一种基数计数方法,使用少量的内存空间完成海量数据的计数统计,在Redis5.0中,HyperLogLog算法得到改进,优化了计数统计时的内存使用效率。 举个例子:B树计数效率非常高,但是内存消耗也比较多。而HyperLogLog可节省大量存储空间。当B树需要1M内存统计,HyperLogLog只需要1kb。 - 内存信息统计报告能力增强 INFO命令返回信息更加详实。 ### 命令新增和优化 1. 客户端管理增强 - Redis-cli支持集群管理 在Redis4.0以及之前版本,需要安装redis-trib模块,管理集群。 Redis5.0对Redis-cli做了优化,集成了集群的所有管理功能。具体使用可以通过命令redis-cli --cluster help查看帮助信息。 - 优化客户端在频繁连接与中断场景下的性能 当您的应用需要使用短连接时,这个优化价值凸显。 2. 有序集合使用更简单 有序集合新增两个命令:ZPOPMIN和ZPOPMAX。 - ZPOPMIN key [count] 删除并返回有序集合key中的最多count个具有最低得分的成员。如果返回多个成员,也会按照得分高低(value值比较),从低到高排列。 - ZPOPMAX key [count] 删除并返回有序集合key中的最多count个具有最高得分的成员。如果返回多个成员,也会按照得分高低(value值比较),从高到低排列。 3. help增加更多子命令说明 支持help直接查看快速使用攻略,你不再需要每次登陆redis.io去查找。例如,命令行输入stream使用攻略:xinfo help 4. Redis-cli命令输入提示 Redis-cli在输入完整的命令后,会展示参数提醒,帮助用户记忆命令语法格式。 ### RDB支持存储LFU、LRU Redis5.0开始,RDB快照文件中增加存储key逐出策略LRU和LFU: - FIFO:先进先出。最早存储的数据,优先被淘汰。 - LRU:最近最少使用。长期未使用的数据,优先被淘汰。 - LFU:最不经常使用。在一段时间内,使用次数最少的数据,优先被淘汰。 ## usage ```sh git pull origin master git add . && git commit -m "feature: update" git push origin master ``` ## refer - https://redis.io/documentation - http://download.redis.io/releases/ - https://github.com/huangz1990/redis-3.0-annotated - http://blog.huangz.me/diary/2014/how-to-read-redis-source-code.html ## 阅读顺序 ![readorder](http://s01.miaobixiaoxiong.com/images/personal/redis-order.png) 第一阶段 阅读Redis的数据结构部分 - 内存分配 zmalloc.c和zmalloc.h - 动态字符串 sds.h和sds.c - 双端链表 adlist.c和adlist.h - 字典 dict.h和dict.c - 跳跃表 server.h文件里面关于zskiplist结构和zskiplistNode结构,以及t_zset.c中所有zsl开头的函数,比如 zslCreate、zslInsert、zslDeleteNode等等。 - 基数统计 hyperloglog.c 中的 hllhdr 结构, 以及所有以 hll 开头的函数 第二阶段 熟悉Redis的内存编码结构 - 整数集合数据结构 intset.h和intset.c - 压缩列表数据结构 ziplist.h和ziplist.c 第三阶段 熟悉Redis数据类型的实现 - 对象系统 object.c - 字符串键 t_string.c - 列表建 t_list.c - 散列键 t_hash.c - 集合键 t_set.c - 有序集合键 t_zset.c中除 zsl 开头的函数之外的所有函数 - HyperLogLog键 hyperloglog.c中所有以pf开头的函数 第四阶段 熟悉Redis数据库的实现 - 数据库实现 redis.h文件中的redisDb结构,以及db.c文件 - 通知功能 notify.c - RDB持久化 rdb.c - AOF持久化 aof.c 以及一些独立功能模块的实现 - 发布和订阅 redis.h文件的pubsubPattern结构,以及pubsub.c文件 - 事务 redis.h文件的multiState结构以及multiCmd结构,multi.c文件 第五阶段 熟悉客户端和服务器端的代码实现 - 事件处理模块 ae.c/ae_epoll.c/ae_evport.c/ae_kqueue.c/ae_select.c - 网路链接库 anet.c和networking.c - 服务器端 redis.c - 客户端 redis-cli.c - 这个时候可以阅读下面的独立功能模块的代码实现 - lua脚本 scripting.c - 慢查询 slowlog.c - 监视 monitor.c 第六阶段 这一阶段主要是熟悉Redis多机部分的代码实现 - 复制功能 replication.c - Redis Sentinel sentinel.c - 集群 cluster.c 其他代码文件介绍 关于测试方面的文件有: - memtest.c 内存检测 - redis_benchmark.c 用于redis性能测试的实现。 - redis_check_aof.c 用于更新日志检查的实现。 - redis_check_dump.c 用于本地数据库检查的实现。 - testhelp.c 一个C风格的小型测试框架。 一些工具类的文件如下: - bitops.c GETBIT、SETBIT 等二进制位操作命令的实现 - debug.c 用于调试时使用 - endianconv.c 高低位转换,不同系统,高低位顺序不同 - help.h 辅助于命令的提示信息 - lzf_c.c 压缩算法系列 - lzf_d.c 压缩算法系列 - rand.c 用于产生随机数 - release.c 用于发布时使用 - sha1.c sha加密算法的实现 - util.c 通用工具方法 - crc64.c 循环冗余校验 - sort.c SORT命令的实现 - 一些封装类的代码实现: - bio.c background I/O的意思,开启后台线程用的 - latency.c 延迟类 - migrate.c 命令迁移类,包括命令的还原迁移等 - pqsort.c 排序算法类 - rio.c redis定义的一个I/O类 - syncio.c 用于同步Socket和文件I/O操作 ## 源码文件-src ### adlist ### ae ### ae_epoll ### ae_evport ### ae_kqueue ### ae_select ### anet ### aof ref: https://searchdatabase.techtarget.com.cn/7-19848/ 利用RDB和利用AOF启动上,其启动时间有一些差别。RDB的启动时间会更短,原因有两个,一是RDB文件中每一条数据只有一条记录,不会像AOF日志那样可能有一条数据的多次操作记录。所以每条数据只需要写一次就行了。另一个原因是RDB文件的存储格式和Redis数据在内存中的编码格式是一致的,不需要再进行数据编码工作。在CPU消耗上要远小于AOF日志的加载。 rdb数据紧凑、文件小、传输和数据恢复速度较快;但可能会丢失较多数据,且rdb文件基本不可读 aof文件基于增量命令,写入的也都是命令,可读性高,数据更完整;缺点是文件较大,会有大量无效历史命令,文件导入恢复速度慢于rdb ### asciilogo ### atomicvar ### bio ### bitops ### blocked ### childinfo ### cluster ### config ### crc16 ### crc64 ### db 数据结构的相关定义都在server.h中,其他一些db操作基本都在db.c中 #### 过期淘汰 对于设置了过期时间的键值对,redis 有2种删除策略:1. 惰性删除 2. 定期删除 定期删除是redisServer的一种时间事件,每隔一段时间就会进行一次遍历删除。之后分析redisServer和事件机制的时候再细说,这里主要看惰性删除。 所谓惰性删除就是不主动删除键值对,只有在读写数据之前,对需要操作的key进行检测,如果过期则进行删除操作。通过这样的策略,能够减轻cpu的负担,但是对内存不够友好,过期的key不会在第一时间被删除。不过 redis 还有定期删除和lru策略,从其他方式上减轻了内存的浪费。 所有读写数据库的命令在执行之前都会调用expireIfNeeded函数,用来判断对应key是否过期 expireIfNeeded的源码中有几个小细节还是值得关注一下的: - 如果当前redis数据库是从库的话,将不会主动进行过期键值对淘汰,只会返回是否过期; - 为了保证aof文件中不冗余过期数据,在淘汰过期key的时候会主动给aof文件添加一条del命令; - 从dbDelete函数的注释中可以看到上文提到的expires和dict共用key对象,并且在删除expires的时候并不会删除key对象,在后续删除dict键值对时才会进行删除。 由于expires的dictType中的keyDestructor和valDestructor都是NULL,因此共用的key对象并不会在移除过期时间时进行被释放,而expires的val是一个int64_t也不需要特殊的释放函数,直接通过zfree节点就能删除键值对了。 ### debug ### debugmacro ### defrag ### dict ref: http://czrzchao.com/redisSourceDict#dict ### endianconv ### evict ### expire ### fmacros ### geo ### geohash ### geohash_helper ### help ### hyperloglog ### intset ref: http://czrzchao.com/redisSourceIntset 整数集合是 redis 对外数据结构set的底层实现之一,当集合元素不大于设定值并且元素都是整数时,就会用intset作为set的底层数据结构。 intset的内存是连续的,所有的数据增删改查操作都是在内存地址偏移的基础上进行的,并且整数的保存也是有序的。 由于intset是在内存上直接操作赋值,并且所存储的值都超过了一个字节,所以需要考虑大小端的问题: 大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。 小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。 redis 的所有存储方式都是小端存储,在endianconv.h中有一段大小端的宏定义,如果当前cpu的字节序为大端就进行相应的转换: ``` #if (BYTE_ORDER == LITTLE_ENDIAN) #define memrev16ifbe(p) #define memrev32ifbe(p) #define memrev64ifbe(p) #define intrev16ifbe(v) (v) #define intrev32ifbe(v) (v) #define intrev64ifbe(v) (v) #else #define memrev16ifbe(p) memrev16(p) #define memrev32ifbe(p) memrev32(p) #define memrev64ifbe(p) memrev64(p) #define intrev16ifbe(v) intrev16(v) #define intrev32ifbe(v) intrev32(v) #define intrev64ifbe(v) intrev64(v) #endif ``` ### latency ### lazyfree ### lzf ### lzfP ### lzf_c ### lzf_d ### memtest ### module ### multi ### networking ### notify ### object ### pqsort ### pubsub ### quicklist ref: http://czrzchao.com/redisSourceQuicklist#quicklist quicklist是一个3.2版本之后新增的基础数据结构,是 redis 自定义的一种复杂数据结构,将ziplist和adlist结合到了一个数据结构中。主要是作为list的基础数据结构。 在3.2之前,list是根据元素数量的多少采用ziplist或者adlist作为基础数据结构,3.2之后统一改用quicklist,从数据结构的角度来说quicklist结合了两种数据结构的优缺点,复杂但是实用: - 链表在插入,删除节点的时间复杂度很低;但是内存利用率低,且由于内存不连续容易产生内存碎片 - 压缩表内存连续,存储效率高;但是插入和删除的成本太高,需要频繁的进行数据搬移、释放或申请内存 而quicklist通过将每个压缩表用双向链表的方式连接起来,来寻求一种收益最大化。 quicklist是 redis 在ziplist和adlist两种数据结构的基础上融合而成的一个实用的复杂数据结构 quicklist在3.2之后取代adlist和ziplist作为list的基础数据类型 quicklist的大部分api都是直接复用ziplist quicklist的单个节点最大存储默认为8kb quicklist提供了基于lzf算法的压缩api,通过将不常用的中间节点数据压缩达到节省内存的目的 ### rand ### rax ### rax_malloc ### rdb RDB有两种触发方式,首先是通过client命令手动触发,有SAVE和BGSAVE两种方式;还有一种是被动触发,通过配置一定条件,自动触发BGSAVE命令。 rdbSaveBackground就是BGSAVE命令调用的函数,该函数会fork一个子进程执行SAVE操作,使服务主进程不被阻塞。并且由于linux copy-on-write的特性,正常情况下不会出现内存使用翻倍的情况。 有个小细节,在退出子进程的时候,redis 采用的是`_exit`而不是exit,因为父进程可能对文件对象进行操作,exit会对清除IO缓存,可能会父进程造成影响。 殊途同归,不论是自动触发还是SAVE和BGSAVE,最终都会走到rdbSave函数. 要点有二: - 通过先创建临时文件,写入后再原子性的rename,确保rdb文件都是完整可用的 - 出现了一个叫做rio的数据类型,并且被初始化为file类型 ### redis-benchmark ### redis-check-aof ### redis-check-rdb ### redis-cli ### redisassert ### redismodule ### release ### replication ### rio rio是 redis 的io封装,所有socket、file、buffer的io都封装在rio中,rdb就是将rio初始化为file类型,进行文件的读写操作。除了rio,redis 还有对后台io操作封装的bio。 ### scripting ### sds ref: https://segmentfault.com/a/1190000012262739 ref: http://czrzchao.com/redisSourceSds#sds SDS本质上就是char *,因为有了表头sdshdr结构的存在,所以SDS比传统C字符串在某些方面更加优秀,并且能够兼容传统C字符串。 sds在Redis中是实现字符串对象的工具,并且完全取代char*..sds是二进制安全的,它可以存储任意二进制数据,不像C语言字符串那样以‘\0’来标识字符串结束, 因为传统C字符串符合ASCII编码,这种编码的操作的特点就是:遇零则止 。即,当读一个字符串时,只要遇到’\0’结尾,就认为到达末尾,就忽略’\0’结尾以后的所有字符。因此,如果传统字符串保存图片,视频等二进制文件,操作文件时就被截断了。 SDS表头的buf被定义为字节数组,因为判断是否到达字符串结尾的依据则是表头的len成员,这意味着它可以存放任何二进制的数据和文本数据,包括’\0’ SDS 和传统的 C 字符串获得的做法不同,传统的C字符串遍历字符串的长度,遇零则止,复杂度为O(n)。而SDS表头的len成员就保存着字符串长度,所以获得字符串长度的操作复杂度为O(1)。 总结下sds的特点是:可动态扩展内存、二进制安全、快速遍历字符串 和与传统的C语言字符串类型兼容 sds结构一共有五种Header定义,其目的是为了满足不同长度的字符串可以使用不同大小的Header,从而节省内存。 Header部分主要包含以下几个部分: - len:表示字符串真正的长度,不包含空终止字符 - alloc:表示字符串的最大容量,不包含Header和最后的空终止字符 - flags:表示header的类型。 ### sdsalloc ### sentinel ### server #### 跳跃表 zskiplist ref: http://czrzchao.com/redisSourceSkiplist 简单的说跳跃表就是在一个有序的集合上加上多层节点,每层节点都是在下层节点的基础上进行跳跃建立索引,并通过随机的方式决定下层节点是否要建立上层索引,使索引的节点尽可能随机离散。通过多级的跳跃节点,跳跃表能够快速的查找到对应节点,大大减少比较次数,和红黑树相比,跳跃表的结构十分简单,代码实现更为简单。 1. 跳跃表是一种有序的链表,持有多层索引,利用空间换取时间,平均查找效率为O(logN) 2. redis 的跳跃表底层为双向链表,并持有尾指针方便从尾遍历 3. reids 的跳跃表最大索引层数为32层,用于支持2^32个元素的索引建立 4. 出于节省内存的目的,redis 的跳跃表每个元素到上一层索引的概率为0.25 #### redisObject ref: http://czrzchao.com/redisSourceObject ref: redis 内存管理 https://www.cnblogs.com/jandison/p/6902396.html redisObject.type 用于标识 string、hash、list、set、zset 五种数据类型, redisObject.encoding 用于标识底层数据结构。 通过这两个字段的组合,同一种数据类型也有多种实现方式,一个完整的映射关系如下表: | 类型 type | 编码 encode | 描述 | | :--------- | :--------------------- | :----------------------------- | | OBJ_STRING | OBJ_ENCODING_INT | 使用整数实现的字符串对象 | | OBJ_STRING | OBJ_ENCODING_EMBSTR | 使用embstr编码实现的字符串对象 | | OBJ_STRING | OBJ_ENCODING_RAW | 使用sds实现的字符串对象 | | OBJ_LIST | OBJ_ENCODING_QUICKLIST | 使用quicklist实现的列表对象 | | OBJ_HASH | OBJ_ENCODING_ZIPLIST | 使用压缩表实现的hash对象 | | OBJ_HASH | OBJ_ENCODING_HT | 使用字典实现的hash对象 | | OBJ_SET | OBJ_ENCODING_INSET | 使用整数集合实现的集合对象 | | OBJ_SET | OBJ_ENCODING_HT | 使用字典实现的集合对象 | | OBJ_ZSET | OBJ_ENCODING_ZIPLIST | 使用压缩列表实现的有序集合对象 | | OBJ_ZSET | OBJ_ENCODING_SKIPLIST | 使用跳跃表实现的有序集合对象 | #### string string有3种编码方式,分别是OBJ_ENCODING_INT、OBJ_ENCODING_EMBSTR和OBJ_ENCODING_RAW。 当一个字符串能被转换为long时,将会采用OBJ_ENCODING_INT 而当字符串长度小于44时,会采用OBJ_ENCODING_EMBSTR否则就会采用OBJ_ENCODING_RAW embstr字符串和raw字符串的不同点在于:embstr的sds空间和object的存储空间是同时申请的,是连续的。 现代的计算机的结构上边在CPU和内存之间存在一个缓存结构,用来协调CPU的高效和访存的相对缓慢的矛盾。平时听到的L1 Cache,L2 Cache,L3 Cache就是这个缓存。当CPU要访问内存之前会先在缓存里面找一找看有没有,如果没有,就去内存找,找到之后放到缓存里面。这个缓存的最小单位一般是64字节,一次性缓存连续的64个字节,这个最小的单位称为缓存行。 在Redis中,每个value对象都有一个redisObject对象头,对于Redis的字符串对象,当读取数据时,拿到`*ptr`指针,然后再去找到指向的SDS对象,如果这个对象距离很远,就会影响Redis读取的效率。因此在Redis中设计了一种特殊的编码结构,这种结构就是embstr,它把redisObject请求头和SDS对象紧紧地挨到一起,然后整体放到一个缓存行中去,这样,在查询的时候就可以直接从缓存中获取到相关的数据,提高了查询的效率。 这样做将原本的一个string对象的两次内存申请优化到了一次[https://blog.csdn.net/zlts000/article/details/81952277 embstr与raw的区别],并且在释放的时候也只需要一个free。由于embstr的所有数据都保存在连续的内存中,可以更好的利用缓存带来的优势。 对于embstr,redis没有提供任何修改的函数。例如当一个embstr被执行APPEND命令时,会被先转换为raw字符串,再进行拼接。 #### list 在3.2.9中quicklist取代了之前的linkedlist和ziplist #### hash - 当hash对象的所有键值对都小于64byte且hash对象的键值对数量少于512时会采用ziplist编码,否则会采用ht字典编码 - 当采用ziplist编码时,键值对按照先后顺序存储,每个键值对中field和value连续存储 - 64和512都是redis默认的限制,可以通过配置文件中的 hash-max-ziplist-entries 和 hash-max-ziplist-value 对hash对象进行配置 #### set set的底层编码可以是iniset或hashtable,以sadd命令为例对set的编码规则进行解析 - 当set对象的所有元素都是数字且元素数量少于512时会采用intset编码,否则会采用ht字典编码 - 512是redis默认的限制,可以通过配置文件中的 set-max-intset-entries 对set对象自定义进行配置 #### zset zset的有ziplist和skiplist两种编码方式。其中skiplist的编码方式是用skiplist和hashTable对数据进行存储 - 当zset对象的所有元素都数据长度小于64byte且元素数量少于128时会采用ziplist编码,否则会采用skiplist编码 - 128和64都是redis默认的限制,可以通过配置文件中的 zset-max-ziplist-entries 和 zset-max-ziplist-value 两个配置项对zset对象自定义进行配置 - 当编码为编码为skiplist时,object中持有的实际数据结构为zset。而zset持有一个skiplist和一个hashTable指针。通过skiplist和hashTable两种数据结构可以同时高效满足zset的范围需求和精确操作需求 - hashTable和skiplist的元素数据为共享的,并不会保存两份数据。hashTable的key为元素数据,value为元素的分值。 #### int serverCron() ### setproctitle ### sha1 ### siphash ### slowlog ### solarisfixes ### sort ### sparkline ### syncio ### t_hash ### t_list ### t_set ### t_string ### t_zset ### testhelp ### util ### valgrind ### version ### ziplist ref: http://czrzchao.com/redisSourceZiplist ziplist是 redis 节省内存的典型例子之一,这个数据结构通过特殊的编码方式将数据存储在连续的内存中。在3.2之前是list的基础数据结构之一,在3.2之后被quicklist替代。但是仍然是zset底层实现之一。 ### zipmap ### zmalloc 这部分是用来申请内存的,之所以单独成了一部分在于redis希望能够将不同系统提供的api统一起来,另外还有一部分系统无法获取malloc数目,因此在这里也进行了一部分的封装;这部分内容很简单,实际上就是malloc, calloc, realloc, free几个操作的变形 ## 附录:各个源码文件的作用简介 +-------------------------------------------------------------------+-------------------------------------------------------------------+ | 文件 | 作用 | +===================================================================+===================================================================+ | ``adlist.c`` 、 ``adlist.h`` | 双端链表数据结构的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``ae.c`` 、 ``ae.h`` 、 ``ae_epoll.c`` 、 ``ae_evport.c`` 、 | 事件处理器,以及各个具体实现。 | | ``ae_kqueue.c`` 、 ``ae_select.c`` | | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``anet.c`` 、 ``anet.h`` | Redis 的异步网络框架,内容主要为对 socket 库的包装。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``aof.c`` | AOF 功能的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``asciilogo.h`` | 保存了 Redis 的 ASCII LOGO 。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``bio.c`` 、 ``bio.h`` | Redis 的后台 I/O 程序,用于将 I/O 操作放到子线程里面执行, | | | 减少 I/O 操作对主线程的阻塞。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``bitops.c`` | 二进制位操作命令的实现文件。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``blocked.c`` | 用于实现 BLPOP 命令和 WAIT 命令的阻塞效果。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``cluster.c`` 、 ``cluster.h`` | Redis 的集群实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``config.c`` 、 ``config.h`` | Redis 的配置管理实现,负责读取并分析配置文件, | | | 然后根据这些配置修改 Redis 服务器的各个选项。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``crc16.c`` 、 ``crc64.c`` 、 ``crc64.h`` | 计算 CRC 校验和。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``db.c`` | 数据库实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``debug.c`` | 调试实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``dict.c`` 、 ``dict.h`` | 字典数据结构的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``endianconv.c`` 、 ``endianconv.h`` | 二进制的大端、小端转换函数。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``fmacros.h`` | 一些移植性方面的宏。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``help.h`` | ``utils/generate-command-help.rb`` 程序自动生成的命令帮助信息。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``hyperloglog.c`` | HyperLogLog 数据结构的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``intset.c`` 、 ``intset.h`` | 整数集合数据结构的实现,用于优化 SET 类型。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``lzf_c.c`` 、 ``lzf_d.c`` 、 ``lzf.h`` 、 ``lzfP.h`` | Redis 对字符串和 RDB 文件进行压缩时使用的 LZF 压缩算法的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``Makefile`` 、 ``Makefile.dep`` | 构建文件。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``memtest.c`` | 内存测试。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``mkreleasehdr.sh`` | 用于生成释出信息的脚本。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``multi.c`` | Redis 的事务实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``networking.c`` | Redis 的客户端网络操作库, | | | 用于实现命令请求接收、发送命令回复等工作, | | | 文件中的函数大多为 write 、 read 、 close 等函数的包装, | | | 以及各种协议的分析和构建函数。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``notify.c`` | Redis 的数据库通知实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``object.c`` | Redis 的对象系统实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``pqsort.c`` 、 ``pqsort.h`` | 快速排序(QuickSort)算法的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``pubsub.c`` | 发布与订阅功能的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``rand.c`` 、 ``rand.h`` | 伪随机数生成器。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``rdb.c`` 、 ``rdb.h`` | RDB 持久化功能的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``redisassert.h`` | Redis 自建的断言系统。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``redis-benchmark.c`` | Redis 的性能测试程序。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``redis.c`` | 负责服务器的启动、维护和关闭等事项。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``redis-check-aof.c`` 、 ``redis-check-dump.c`` | RDB 文件和 AOF 文件的合法性检查程序。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``redis-cli.c`` | Redis 客户端的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``redis.h`` | Redis 的主要头文件,记录了 Redis 中的大部分数据结构, | | | 包括服务器状态和客户端状态。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``redis-trib.rb`` | Redis 集群的管理程序。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``release.c`` 、 ``release.h`` | 记录和生成 Redis 的释出版本信息。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``replication.c`` | 复制功能的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``rio.c`` 、 ``rio.h`` | Redis 对文件 I/O 函数的包装, | | | 在普通 I/O 函数的基础上增加了显式缓存、以及计算校验和等功能。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``scripting.c`` | 脚本功能的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``sds.c`` 、 ``sds.h`` | SDS 数据结构的实现,SDS 为 Redis 的默认字符串表示。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``sentinel.c`` | Redis Sentinel 的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``setproctitle.c`` | 进程环境设置函数。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``sha1.c`` 、 ``sha1.h`` | SHA1 校验和计算函数。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``slowlog.c`` 、 ``slowlog.h`` | 慢查询功能的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``solarisfixes.h`` | 针对 Solaris 系统的补丁。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``sort.c`` | SORT 命令的实现。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``syncio.c`` | 同步 I/O 操作。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``testhelp.h`` | 测试辅助宏。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``t_hash.c`` 、 ``t_list.c`` 、 ``t_set.c`` 、 ``t_string.c`` 、 | 定义了 Redis 的各种数据类型,以及这些数据类型的命令。 | | ``t_zset.c`` | | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``util.c`` 、 ``util.h`` | 各种辅助函数。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``valgrind.sup`` | valgrind 的suppression文件。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``version.h`` | 记录了 Redis 的版本号。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``ziplist.c`` 、 ``ziplist.h`` | ZIPLIST 数据结构的实现,用于优化 LIST 类型。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``zipmap.c`` 、 ``zipmap.h`` | ZIPMAP 数据结构的实现,在 Redis 2.6 以前用与优化 HASH 类型, | | | Redis 2.6 开始已经废弃。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+ | ``zmalloc.c`` 、 ``zmalloc.h`` | 内存管理程序。 | +-------------------------------------------------------------------+-------------------------------------------------------------------+