redis部分源码数据结构图解

2 篇文章 0 订阅
1 篇文章 0 订阅

一、Redis的一些特点

  1. 非关系型的键值对数据库,底层是hashtable,可以根据键以0(1)的时间复杂度取出或插入关联值
  2. Redis的数据基于内存存储的
  3. 键值对中的类型可以是字符串,整型,浮点型等,且键是唯一的
  4. 键值对中的类型可以是string, hash, list, set, sorted_set等
  5. Redis内置了复制,磁盘持久化,LUA脚本, 事务,SSL, ACLS,客户端缓存,客户端代理等功能
  6. 通过Redis哨兵和Redis Cluster模式提供高可用

帮助命令查看详细使用说明:help @string

二、Redis k-v存储结构

源码解析

/* Redis database representation. There are multiple databases identified
 * by integers from 0 (the default database) up to the max configured
 * database. The database number is the 'id' field in the structure. */
typedef struct redisDb {
    dict *dict;                 /* The keyspace for this DB */
    dict *expires;              /* Timeout of keys with a timeout set */
    dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP)*/
    dict *ready_keys;           /* Blocked keys that received a PUSH */
    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */
    int id;                     /* Database ID */
    long long avg_ttl;          /* Average TTL, just for stats */
    unsigned long expires_cursor; /* Cursor of the active expire cycle. */
    list *defrag_later;         /* List of key names to attempt to defrag one by one, gradually. */
} redisDb;
typedef struct dict {
    dictType *type;
    void *privdata;
    dictht ht[2];
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    unsigned long iterators; /* number of iterators currently running */
} dict;
typedef struct dictType {
    uint64_t (*hashFunction)(const void *key);
    void *(*keyDup)(void *privdata, const void *key);
    void *(*valDup)(void *privdata, const void *obj);
    int (*keyCompare)(void *privdata, const void *key1, const void *key2);
    void (*keyDestructor)(void *privdata, void *key);
    void (*valDestructor)(void *privdata, void *obj);
} dictType;

/* This is our hash table structure. Every dictionary has two of this as we
 * implement incremental rehashing, for the old to the new table. */
typedef struct dictht {
    dictEntry **table;
    unsigned long size;
    unsigned long sizemask;
    unsigned long used;
} dictht;
typedef struct dictEntry {
    void *key;
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;
    struct dictEntry *next;
} dictEntry;

redis db

三、Redis Key的底层存储结构:SDS(Simple Dynamic String)

源码结构

// redis3.2之前数据结构:
struct sdshdr { // c语言struct结构体,相当于java的class
	// buf中已使用长度,int是4byte 所以范围是 --> 0 ~ 2^32 - 1  
	unsigned int len;    
	// buf中未使用长度    
	unsigned int free;    
	// 保存字符串    
	char buf[];
}; // sds的扩容:新增后长度小于 1MB,新长度的2倍新增后长度大于 1MB ,新长度加上1MB源码
// Redis3.2之后共有五种类型的SDS(长度分别为小于5bit、1字节、2字节、4字节、8字节)。
struct __attribute__ ((__packed__)) sdshdr5 {    
	unsigned char flags; /* 低3位存储类型, 高5位存储长度 */    
	char buf[]; // len < 2^5
};
struct __attribute__ ((__packed__)) sdshdr8 {    
	uint8_t len; /* 已使用,1字节 */    
	uint8_t alloc; /* 总长度,用1字节存储 */    
	unsigned char flags; /* 低3位存储类型, 高5位预留 */    
	char buf[]; // len < 2^8
};
struct __attribute__ ((__packed__)) sdshdr16 {    
	uint16_t len; /* 已使用,2字节 */    
	uint16_t alloc; /* 总长度,用2字节存储 */    
	unsigned char flags; /* 低3位存储类型, 高5位预留 */    
	char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {    
	uint32_t len; /* 已使用,4字节 */    
	uint32_t alloc; /* 总长度,用4字节存储 */    
	unsigned char flags; /* 低3位存储类型, 高5位预留 */    
	char buf[];
};
struct __attribute__ ((__packed__)) sdshdr64 {    
	uint64_t len; /* 已使用,8字节 */    
	uint64_t alloc; /* 总长度,用8字节存储 */    
	unsigned char flags; /* 低3位存储类型, 高5位预留 */    
	char buf[];
};

sdshdr5、sdshdr8数据结构图解

sds图解

四、Redis value之string类型

查看value类型相关命令

# 1.查看value类型:
type [key]
# 2.查看value编码类型:
object encoding [key]

redis value 的存储结构源码

typedef struct redisObject {
    unsigned type:4; // 4bit 类型:string、list、hash、set、zset
    unsigned encoding:4; // 4bit 编码:int、embstr、raw、ziplist ...
    unsigned lru:LRU_BITS; /* 24bit LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
    int refcount; // 4byte 引用计数法
    void *ptr; // 8byte 实际数据指针
} robj; // 总空间:4bit + 4bit + 24bit + 4byte + 8byte = 16byte

type为string类型时,encoding可能为int、embstr、raw

如果redis val时整数,并且范围在8byte范围内,ptr指针存储的是实际的数据
验证:
当设置int为2^63 - 1时,value编码类型是int
当设置int为2^63时,value编码类型是embstr

> set int 9223372036854775807
OK
> object encoding int
"int"
> set int 9223372036854775808
OK
> object encoding int
"embstr"

如果redis val长度超过44,会变成raw类型
embstr范围分析:因为cpu缓存行时64byte,而redisObject占用16字节,ptr还最大可以使用sdshdr8类型存储,其中len,alloc,flags各占用1byte,buf结尾’\0’占用1byte,所以buf剩余空间最多存储64-16-4=44byte的数据,所以超过44长度时就会转成raw类型的数据,值得注意的是raw类型的值删减后不会回退为embstr
验证:
如果字符串的长度<=44,查看编码类型是embstr
如果字符串的长度>44,编码类型是raw

> set str 12345678901234567890123456789012345678901234
OK
> object encoding str
"embstr"
> set str 123456789012345678901234567890123456789012345
OK
> object encoding str
"raw"

五、Redis value类型之ziplist类型(未完待续…)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值