目前为止,我们介绍了 redis 中非常典型的五种数据结构,从 SDS 到 压缩列表,这都是 redis 最底层、最常用的数据结构,相信你也掌握的不错。
但 redis 实际存储键值对的时候,是基于对象这个基本单位的,并且往往一个对象下面对对应不同的底层数据结构实现以便于在不同的场景下切换底层实现提升效率。例如列表对象在元素不多情况话会使用压缩列表来实现以压缩内存,而在元素比较多的时候常规的双端链表进行实现。
下面我们就具体来看看 redis 中都有哪些对象,底层又对应哪些可供选择的数据结构。
一、Redis 对象结构定义
redis 为每个对象定义为如下数据结构:
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
unsigned lru:LRU_BITS;
int refcount;
void *ptr;
} robj;
type 记录的是当前的对象类型,有以下几种类型:
#define OBJ_STRING 0 /*字符串对象*/
#define OBJ_LIST 1 /*列表对象*/
#define OBJ_SET 2 /*集合对象*/
#define OBJ_ZSET 3 /*有序集合对象*/
#define OBJ_HASH 4 /*哈希对象*/
encoding 记录的是当前对象使用的哪种底层数据结构实现的,有以下类型可供选择:
#define OBJ_ENCODING_RAW 0 /* SDS 字符串 */
#define OBJ_ENCODING_INT 1 /* 整数 */
#define OBJ_ENCODING_HT 2 /* 字典结构 */
#define OBJ_ENCODING_ZIPMAP 3 /* 压缩map,已经废弃 */
#define OBJ_ENCODING_LINKEDLIST 4 /* LinkedList 双端链表,废弃了 */
#define OBJ_ENCODING_ZIPLIST 5 /* 压缩列表 */
#define OBJ_ENCODING_INTSET 6 /* 整数集合 */
#define OBJ_ENCODING_SKIPLIST 7 /* 跳跃表 */
#define OBJ_ENCODING_EMBSTR 8 /* 短字符串 */
#define OBJ_ENCODING_QUICKLIST 9 /* 压缩链表和双向链表组成的快速列表 */
8 和 9 我们遇到时在介绍,这里暂时不做介绍。
lru 记录的是上一个当前对象实例被访问的时间,它用作计算对象空转时长,空转时长过大的对象会被 redis 优先释放内存。
refcount 记录的是对象的引用计数,引用计数算法是很多编程语言中管理对象是否应该被销毁的依据,和它类似的典型的 Java 中可达性分析算法,都是用于计数当前对象是否依然被使用,以便释放内存。
ptr 指针指向的是实际实现当前对象的数据结构首地址。
以上就是 redisObject 数据结构的基本解释,下面我们看具体的对象分别会在什么情况下切换不同的底层实现。