1. 如何阅读数据结构相关的源码
阅读redis数据结构相关的源码,可以从命令定义的地方看,这里就是所有命令的操作入口函数,点进去就知道每个命令底层是基于什么数据结构实现的了。commands.def文件里面redisCommandTable就是所有的命令的定义了。
1 | struct COMMAND_STRUCT redisCommandTable[] = { |
2. 一切皆redisObject
1 | struct redisObject { |
redis的所有数据是放在一个大的hash table(redis中叫dict)里面的,这个hash table里面key是string(redis里面的sds),value就是这个redisObject。这个value是一个抽象的数据结构,底层有不同的实现(甚至会有多个数据结构组成,比如zset的skiplist编码就是通过dict和skiplist一起实现的),统一封装成了一个redisObject的对象。
unsignedtype:4;有下面几种,用来区分这个对象是什么,我们说redis支持ZSET,就是这个字段定义的。
1
2
3
4
5
6
7
8每个redisObject底层可以有多种实现方式,这个是用unsigned encoding:4;字段表示的,比如ZSET类型的数据结构可能有LISTPACK和SKIPLIST的实现。
1
2
3
4
5
6
7
8
9
10
11
12
13void *ptr;这是一个通用的指针,这里就是实际指向的底层的数据结构的对象了。
int refcount;这个是对这个对象的引用计数,创建对象计数设置为1,减少到0,对象会被释放,不同encoding调用不同的释放函数。
unsigned lru:LRU_BITS;这是用来实现lru的,这里不详细说了,后面专门介绍。
3. redisObject的接口
1 | |
4. decrRefCount
1 | |
对redisObject的引用数量的维护,还有一个增加引用数量的接口incrRefCount,以及另外一个没有再用的接口decrRefCountVoid。
引用有3种:
- OBJ_SHARED_REFCOU NT是全局对象,永远不会被删除
- OBJ_STATIC_REFCOUNT是栈上的对象
- 其余的都是正常引用计数的对象
引用计数,可以用来共享对象,比如redis启动的时候,就会生成0-9999的共享对象,
还有一些协议共用的string
1 | void createSharedObjects(void) { |