redis源码阅读02

字符串 SDS(Simple Dynamic String)

1.定义

可以看到sds就是一个字符动态数组,只是多了2个属性,一个表示总长度(len),另一个表示没有使用的长度(free)

typedef char *sds;
struct sdshdr {
    // buf 中已占用空间的长度
    int len;
    // buf 中剩余可用空间的长度
    int free;
    // 数据空间
    char buf[];
};

2.优点

  • O(1)内获得字符串长度
  • 杜绝缓冲区溢出(通过free属性)
  • 减少内存分配次数(空间预分配和惰性空间释放),执行操作前调用sdsMakeRoomFor函数.
  • 二进制安全
//分配后确保buf 至少会有 addlen + 1 长度的空余空间(+1表示'\0')
sds sdsMakeRoomFor(sds s, size_t addlen);

双端链表结构 list与listNode

redis源码阅读02_第1张图片

2.优点

双向、无环、带有头指针和尾指针、带有长度.

#define listLength(l) ((l)->len)
#define listFirst(l) ((l)->head)
#define listLast(l) ((l)->tail)

字典

采用hash表实现,每一个表由多个哈希节点组成,每个哈希节点保存了一个键值对.

load_factor =ht[0].used / ht[0].size

redis实现哈希的代码是:

hash =dict->type->hashFunction(key);
index = hash& dict->ht[x].sizemask;
//ht是包含两个项的数组,每个项是一个哈希表,一般情况下只是用ht[0],只有在对ht[0]进行rehash时,才会使用ht[1],在rehash过程(过大、过小),ht[1]保存这最新的存储空间,将ht[0]中的全部内容复制到ht[1]后,将ht[0]设置为ht[1],然后释放ht[0]
//每个字典都使用两个哈希表,从而实现渐进式 rehash(从ht[1]-->ht[0]的过程是分多次) 。
typedef struct dictht {
    // 哈希表数组
    dictEntry **table;
    // 哈希表大小
    unsigned long size;
    
    // 哈希表大小掩码,用于计算索引值
    // 总是等于 size - 1
    unsigned long sizemask;

    // 该哈希表已有节点的数量
    unsigned long used;

} dictht;

redis源码阅读02_第2张图片

特点

  • 当redis计算hash时,采用的是MurmurHash2哈希算法。
  • 渐进式rehash分而治之。1。同时存在ht[1]和ht[0],2.对哈希表的查找、修改、删除,会先在ht[0]进行,ht[0]没有,在ht[1]寻找,增加的操作,会直接增加到ht[1]中。当某个时间节点,全部的ht[0]都迁移到ht[1]后,rehashidx的值重新设定为-1,表示rehash完成。
  • 采用链地址法解决hash冲突

整数集合

当一个集合只包含整数值元素,redis会考虑将其作为集合键

typedef struct intset {
    // 编码方式
    uint32_t encoding;
    uint32_t length;
    // 保存元素的数组
    int8_t contents[];
} intset;

redis源码阅读02_第3张图片])

特点

无重复。

压缩列表ziplist

ziplist一系列特殊编码的连续内存块组成的数据结构,是列表键和哈希键的底层实现之一(元素个数少)。

redis源码阅读02_第4张图片

跳跃表的视角来看,可以说 Redis 对象是根据score来排序的。

对象

Redis对象系统中包含字符串对象、列表对象、哈希对象、集合对象、有序集合对象。

Redis实现了基于引用计数的内存回收机制。

typedef struct redisObject {
    // 类型
    unsigned type:4;
    // 编码
    unsigned encoding:4;
    // 对象最后一次被访问的时间
    unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */
    // 引用计数
    int refcount;
    // 指向实际值的指针
    void *ptr;
} robj;

AOF持久化

通过保存Redis服务器所执行的写命令,来记录数据库状态。实现可分为命令追加(append)、文件写入、文件同步(sync)三个步骤。

你可能感兴趣的:(java)