- Redis源码怎么查看
- Redis源码两个核心文件server.h、dict.h
- server.h文件
- redisObject定义
- redisDb定义
- dict.h文件
- dict定义:引用dictht
- dictht定义:Redis定义的hash表,引用dictEntry
- dictEntry定义:dictEntry(翻译过来就是字典条目),定义key和value
- sds.h文件:简单动态字符串,Redis自己实现的字符串,所有的key都是SDS结构
- SDS是什么:简单动态字符串
- sds.h文件的sdshdr8的源码截取
- Redis为什么要用SDS来实现字符串?
- Redis各数据结构命令、源码分析、应用场景
Redis源码怎么查看Redis是KV存储机构的,
这种key、 value的存储方式,Redis一般会用hash表来进行存储,Redis的最外层也是使用的hash表,Redis还有一个hash的数据结构,那个叫做内层的hash。那么内层的hash是怎么实现的?
可以去官网找你想要的版本:https://redis.io/download/
我用的版本是6.0.16。
首先下载redis压缩包,https://download.redis.io/releases/redis-6.0.16.tar.gz
解压,进入解压后的redis目录下的src文件夹,redis的所有源代码都存放在此。
Redis源码两个核心文件server.h、dict.h,这两个也是最基本的文件。
server.h文件 redisObject定义dictEntry的val可以不同数据结构类型,因此很乱,
所以设计了redisObject统一管理不同类型的val数据结构,
dictEntry的val指向redisObject,
redisObject的*ptr指向对象实际的数据结构
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
unsigned lru:LRU_BITS;
int refcount;
void *ptr;
} robj;
redisDb定义
typedef struct redisDb {
dict *dict;
dict *expires;
dict *blocking_keys;
dict *ready_keys;
dict *watched_keys;
int id;
long long avg_ttl;
unsigned long expires_cursor;
list *defrag_later;
} redisDb;
dict.h文件
dict定义:引用dictht
typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
long rehashidx;
unsigned long iterators;
} dict;
dictht定义:Redis定义的hash表,引用dictEntry
typedef struct dictht {
dictEntry **table;
unsigned long size;
unsigned long sizemask;
unsigned long used;
} dictht;
dictEntry定义:dictEntry(翻译过来就是字典条目),定义key和value
typedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next;
} dictEntry;
sds.h文件:简单动态字符串,Redis自己实现的字符串,所有的key都是SDS结构
SDS(Simple Dynamic String):简单动态字符串,Redis会根据String类型的value长度,去选择合适的sdshdr数结构来存储这个value。
SDS是什么:简单动态字符串SDS(Simple Dynamic String):简单动态字符串,Redis会根据String类型的value长度,去选择合适的sdshdr数结构来存储这个value,这样的设计可以节省内存空间。
# 换算: 2^10=1024byte=1kb 2^20=1MB 2^30=1GB 2^40=1TB 2^50=1PB 2^60=1EB
sdshdr5:2^5=32byte(不用)
sdshdr8:2^8=256byte
sdshdr16:2^16=65536byte=64kb
sdshdr32:2^32=4GB
sdshdr64:2^64=16EB
Redis的key是字符类型,即String,最大可以用得到是512M,那么它的value字符类型,也是String,最大也是512M。
sdshdr32,sdshdr64定义的这么大,但你未必能用得到全部,这也是Redis预留的一种思想,给你足够多的空间,未来可能就用的到这么大了。
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len;
uint8_t alloc;
unsigned char flags;
char buf[];
};
Redis为什么要用SDS来实现字符串?
C语言里面也是没有字符串的,它有的是字符数组,有以下特点:
- 内存空间预先分配
- 获取字符长度(即字符数组的长度)需要从头到尾先遍历一遍,时间复杂度O(n)
- C语言的字符数组内存分配是固定的,长度变更引起内存重新分配
- 用’ ’判断字符串结束(如果你存的内容恰好包含,也会认为是结束)
所以Redis基于字符数组实现了自己的字符串SDS:简单动态字符串
| C字符数组 | SDS |
|---|---|
| 获取字符长度的复杂度O(N) | 获取字符长度的复杂度O(1),因为SDS中uint8_t len存储当前字符数组的长度 |
| API是不安全的,可能会造成称缓冲区溢出 | API是安全的,不会造成称缓冲区溢出,简单动态字符串可以扩容,而且不需要预先分配,因此不会产生内存溢出 |
| 修改字符长度N次必然需要执行N次内存重新分配 | 修改字符长度N次最多需要执行N次内存重新分配,SDS里面有一个特殊的设计,叫做空间的预分配和惰性的空间释放,不管是获取内存还是释放内存都不是及时的,所以性能会提升 |
| 只能保存文本数据 | 可以保存文本数据或者二进制数据 |
| 可以使用所有 | 可以使用部分 |
Redis源码-String:Redis String命令、Redis String存储原理、Redis字符串三种编码类型、Redis String SDS源码解析、Redis String应用场景



