写点什么

【Redis】数据结构

用户头像
awen
关注
发布于: 4 小时前
【Redis】数据结构

源码分析


基于 redis-6.2.4 源码,src/server.sh

Redis 主要包括 string\list\set\zet\hash 五种基本数据类型,这几种基本数据类型底层由不同的 object encoding 实现,包括 raw、int、hashtable、zipmap、linkedlist、intset、skiplist、embstr、quicklist 等。

/* The actual Redis Object */
#define OBJ_STRING 0
#define OBJ_LIST 1
#define OBJ_SET 2
#define OBJ_ZSET 3
#define OBJ_HASH 4
/* Objects encoding. Some kind of objects like Strings and Hashes can be
* internally represented in multiple ways. The 'encoding' field of the object
* is set to one of this fields for this object. */
#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 */
#define LRU_BITS 24
#define LRU_CLOCK_MAX ((1<<LRU_BITS)-1) /* Max value of obj->lru */
#define LRU_CLOCK_RESOLUTION 1000 /* LRU clock resolution in ms */
#define OBJ_SHARED_REFCOUNT INT_MAX /* Global object never destroyed. */
#define OBJ_STATIC_REFCOUNT (INT_MAX-1) /* Object allocated in the stack. */
#define OBJ_FIRST_SPECIAL_REFCOUNT OBJ_STATIC_REFCOUNT
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency
* and most significant 16 bits access time). */
int refcount;
void *ptr;
} robj;
复制代码

如下为 redis 的基本数据类型及 object encoding 的对应关系:


数据结构

string

底层编码


  1. OBJ_ENCODING_INT:如果一个字符串对象保存的是整数值,并且这个整数值可以用long类型来表示

  2. OBJ_ENCODING_RAW:如果字符串对象保存的是一个字符串值,并且这个字符串值的长度大于 32 字节

  3. OBJ_ENCODING_EMBSTR:如果字符串对象保存的是一个字符串值,并且这个字符申值的长度小于等于 32 字节

应用场景


  1. 缓存热点数据

  2. 计数器、限速器、自增 ID

  3. session 共享

  4. 二进制数据的存储:图片、文件等

hash

底层编码

满足如下两个条件使用 OBJ_ENCODING_ZIPLIST,否则使用 OBJ_ENCODING_HT。

  1. 字典中保存的键和值的大小都要小于 64 字节

  2. 字典中键值对的个数要小于 512 个

应用场景

  1. 购物车

  2. 计数器

  3. 对象缓存

list

底层编码

3.2 以前,满足如下两个条件使用 OBJ_ENCODING_ZIPLIST,否则使用 OBJ_ENCODING_LINKEDLIST。

  • 当列表元素的个数小于 list-max-ziplist-entries(默认 512 个)

  • 当列表中每个元素的值都小于 list-max-ziplist-value(默认 64 字节)

3.2 以后使用 quicklist 取代了 ziplist 和 linkedlist,quicklist 是 ziplist 和 linkedlist 的结合体。附 quicklist.h 部分源码如下:

typedef struct quicklistNode {    struct quicklistNode *prev;    struct quicklistNode *next;    unsigned char *zl;    unsigned int sz;             /* ziplist size in bytes */    unsigned int count : 16;     /* count of items in ziplist */    unsigned int encoding : 2;   /* RAW==1 or LZF==2 */    unsigned int container : 2;  /* NONE==1 or ZIPLIST==2 */    unsigned int recompress : 1; /* was this node previous compressed? */    unsigned int attempted_compress : 1; /* node can't compress; too small */    unsigned int extra : 10; /* more bits to steal for future usage */} quicklistNode;
复制代码

应用场景

  1. 栈:lpush+lpop

  2. 队列:lpush+rpop

  3. 阻塞队列:lpush+brpop

set

底层编码

满足如下两个条件,使用 OBJ_ENCODING_INTSET 实现,否则 OBJ_ENCODING_HT。

  1. 集合中的元素都是整数

  2. 集合中的元素个数小于 set-maxintset-entries(默认 512 个)

应用场景

  1. 标签

  2. 社交场景,共同关注、共同好友等

zset

底层编码

满足如下两个条件使用 OBJ_ENCODING_ZIPLIST,否则使用 OBJ_ENCODING_SKIPLIST。

  1. 集合中保存的元素个数要小于 128 个

  2. 集合中保存的所有元素成员的长度都必须小于 64 字节

应用场景

  1. 排行榜

  2. 销量 topN

用户头像

awen

关注

Things happen for a reason. 2019.11.15 加入

还未添加个人简介

评论

发布
暂无评论
【Redis】数据结构