Redis源码阅读-笔记分享

项目笔记链接: https://github.com/mllijiatu/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 等。

性能优化:对对象的内部表示和存储结构进行了优化,以提高性能和降低内存占用。

安全性改进:加入了对对象的更多安全检查和保护机制,以防止数据损坏和非法访问。

posted @ 2022-08-07 22:38  Ricardo_ML  阅读(438)  评论(0编辑  收藏  举报