Redis源码阅读-笔记分享
简单动态字符串
Redis 中简单动态字符串的实现位于 sds.h 和 sds.c 文件中。
以下是简单动态字符串的定义:
点击查看代码
typedef char *sds;
struct sdshdr {
int len;
int free;
char buf[];
};
这个实现的精妙之处在于:
动态调整大小:简单动态字符串可以根据需要自动调整大小,以容纳不同长度的字符串,这使得字符串操作更加灵活和高效。
使用惰性空间释放:当字符串缩短时,不会立即释放空间,而是保留一部分空闲空间,以减少频繁的内存分配和释放操作。
链表
Redis 中链表的实现位于 adlist.h 和 adlist.c 文件中。以下是链表的定义:
点击查看代码
typedef struct listNode {
struct listNode *prev;
struct listNode *next;
void *value;
} listNode;
typedef struct list {
listNode *head;
listNode *tail;
unsigned long len;
void *(*dup)(void *ptr);
void (*free)(void *ptr);
int (*match)(void *ptr, void *key);
} list;
这个实现的精妙之处在于:
双向链表:使用双向链表实现,可以在常数时间内进行前后插入和删除操作,提高了操作效率。
多态:链表支持多态的节点值,可以存储任意类型的数据,增加了灵活性。
字典
Redis 中字典的实现位于 dict.h 和 dict.c 文件中。以下是字典的定义:
点击查看代码
typedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next;
} dictEntry;
typedef struct dictht {
dictEntry **table;
unsigned long size;
unsigned long sizemask;
unsigned long used;
} dictht;
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;
typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
long rehashidx;
int iterators;
} dict;
这个实现的精妙之处在于:
- 哈希表:使用哈希表实现字典,可以在平均情况下以常数时间复杂度进行查找、插入和删除操作,提高了操作效率。
- 渐进式 rehash:字典支持渐进式 rehash,可以在不阻塞服务的情况下,逐步将哈希表的大小扩大到两倍,并将旧表中的键值对重新映射到新表中,保持了数据的可用性和一致性。
跳跃表
Redis 中跳跃表的实现位于 server.h 和 t_zset.c 文件中。这里是其定义的一部分:
点击查看代码
typedef struct zskiplistNode {
double score;
sds ele;
struct zskiplistNode *backward;
struct zskiplistLevel {
struct zskiplistNode *forward;
unsigned int span;
} level[];
} zskiplistNode;
typedef struct zskiplist {
struct zskiplistNode *header, *tail;
unsigned long length;
int level;
} zskiplist;
跳跃表的精妙之处在于:
高效查找:跳跃表使用多层索引,可以在对数时间内进行查找操作,比传统的链表快速得多。
平衡性:跳跃表在插入和删除操作时会动态调整索引层数,保持了跳跃表的平衡性,避免了退化成链表的情况。
整数集合
Redis 中整数集合的实现位于 intset.h 和 intset.c 文件中。以下是整数集合的定义:
点击查看代码
typedef struct intset {
uint32_t encoding;
uint32_t length;
int8_t contents[];
} intset;
整数集合的精妙之处在于:
紧凑存储:整数集合采用紧凑的存储方式,节省了内存空间。
优化操作:整数集合内部使用特定编码来表示整数值,根据整数值的大小选择不同的编码方式,从而在常数时间内进行查找、插入和删除操作。
第7章 压缩列表
Redis 中压缩列表的实现位于 ziplist.c 文件中。以下是压缩列表的定义:
点击查看代码
#define ZIPLIST_ENTRY_HEAD 0
#define ZIPLIST_ENTRY_TAIL 1
#define ZIPLIST_ENTRY_PAYLOAD 2
typedef struct zlentry {
unsigned int prevrawlensize, prevrawlen;
unsigned int lensize, len;
unsigned int headersize;
unsigned char encoding;
unsigned char *p;
} zlentry;
紧凑存储:压缩列表使用紧凑的存储方式,将多个列表项紧密地存储在一起,节省了内存空间。
灵活编码:压缩列表根据实际数据的大小选择不同的编码方式,可以存储不同长度的整数值和字符串,提高了存储效率。
对象
Redis 中对象的实现位于 object.h 和 object.c 文件中。以下是对象的定义:
点击查看代码
#define OBJ_STRING 0
#define OBJ_LIST 1
#define OBJ_SET 2
#define OBJ_ZSET 3
#define OBJ_HASH 4
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
void *ptr;
unsigned lru:22;
unsigned lru_seconds_idle:22;
} robj;
对象的精妙之处在于:
- 多态性:对象采用多态的设计,可以表示不同类型的数据,如字符串、列表、集合、有序集合和哈希表等。
- 封装性:对象将数据与数据类型封装在一起,提高了数据的安全性和可靠性,同时简化了数据操作的接口。
这些实现展示了 Redis 中各种数据结构的精妙设计和高效实现,为 Redis 提供了高性能和灵活性。
功能增强:随着 Redis 的不断发展,对象的功能不断增强,例如增加了对新数据结构的支持,如 HyperLogLog、Geo 等。
性能优化:对对象的内部表示和存储结构进行了优化,以提高性能和降低内存占用。
安全性改进:加入了对对象的更多安全检查和保护机制,以防止数据损坏和非法访问。