《Redis设计与实现》读书笔记

7.2 压缩节点连锁更新的问题

        一个节点由三部分组成:记录上个节点字节数的pre_entry_len、记录内容的content以及记录当前节点属性的encoding。

        由于每个节点的pre_entry_len部分会记录上一个节点占用的字节数。当content从250 -> 253字节时,会引发下一个节点的pre_entry_len更新,由此下个节点的字节数增加,从而可能引发下下一个节点的pre_entry_len更新,由此最坏情况下节点更新的复杂度为O(n),但这种可能性极小。可以忽略不计。

8.对象

        redis中维护的数据都不是直接用五种数据结构存储的,而是用对象。

        set的key和value都是用对象维护的

typedef struct redisObject{
    // 类型 五种基本类型string, list, hash, set, zset
    unsigned type:4;
    // 编码 eg.整数值实现的字符串、SDS实现的字符串,即不同实现模式的基本类型
    // 压缩列表实现的zset,跳表实现的zset
    unsigned encoding:4;
    // 指向底层实现数据结构的指针
    void *ptr;
    // 引用计数
    int refcount;
    // 记录最后一次被访问的时间
    unsigned lru:32;
}

开始比较疑惑有了type:4字段还要encoding:4作甚,对于存储的值类型还是要用不同实现方法的基本类型,具体场景具体分析的方法论还是有道理的。

        long double类型在redis是以字符串存储的。若用数字类型存储,可能在不同平台传输可能丢精度,用字符串保证了这种情况不会发生。

        不同编码实现的基本存储结构,对应函数的实现可能不同。例如int编码的字符串和embetr、raw编码的字符串的STRLEN函数,int编码需要先将数值转成的字符串再计算字符串长度,而embetr、raw编码的字符串调用sdslen函数即可,而sdslen我们知道是O(1)的。     

        列表有ziplist和linkedlist两种编码

        最大的不同之处在于ziplist直接存的字符串,而linkedlist存的是StringObject对象。

        使用场景:ziplist用于短小的list存储。具体使用条件——存储的字符串大小 < 64字节 且 元素数量小于512。

        看了下ziplist编码使用的list的“LSET”命令,是先删除节点再插入节点,而linkedlist是直接覆盖,这点符合直觉的。为什么ziplist要这样做,考虑要保持内存连续性,先删除再插入可以触发内存分配重排机制。我也不是很清楚为什么直接赋值不行,可能偏低层吧,而且通常覆盖操作是不会完全删除原来数据,比如"123" 改成 "1",考虑到性能,让我实现的话会记录下新字符串的长度和字符串首地址,旧数据不会马上从内存中删除,而是积攒一部分数据后再集体删除。(以上都是我口胡的)

         哈希对象的编码有ziplist和hashtable,hashtable是用字典实现的。

        ziplist编码实现的哈希,其实就是暴力找呗。适用场景是元素数量小于512,这也符合直觉,没啥好说的。

        hashtable编码也不过赘述了,前面讲字典时具体介绍了。

        

        集合对象编码有intset或者hashtbale(跳过)

        有序集合对象编码ziplist和skiplist,提一下zset是有一个字段专门存储k - v映射,如下图。

        内存回收 (引用计数)         

        对象共享(类似共享内存,两个相同值就值向同一片内存)。书中有说Redis不共享包含字符串的对象,是因为验证(即Object.equal(a,b))包含多个字符串的对象的复杂度是O(n^2),我理解可以给字符串对象加个哈希值不就能降到O(n)了。

        对象的空转时间(空闲时间) = 当前时间 - 上次访问时间

 二. 单机数据库的实现

        9. 5 过期键删除策略——定时删除、惰性删除、定期删除

        ps:感觉都是之前背过的八股(

        定时删除:key创建时同时创建一个定时器,到过期时间自动删除

                缺点:高并发时对cpu占用大,每个key多要单独删除

        惰性删除:调用key时检查key是否过期

                缺点:对内存不友好,过期key存于内存中

        定期删除:每隔一段时间,批量删除过期key

                缺点:上面两者的中间情况,具体要看定期删除的策略——参数为时间间隔、删除key数量限制

10.RDB持久化

        RDB文件是在redis服务器启动时自动载入的,并没有直接载入的命令。

        SAVE和BGSAVE命令可用来保存当前数据。其中SAVE会阻塞主进程,而BGSAVE是fork子进程进行保存

        AOF开启的情况下,会优先使用AOF来还原redis。

RDB文件结构

​​​​​​REDIS:即保存的是"REDIS"字符的二进制,作为RDB文件的标识

db_version:版本号

databases: 存的数据库数据

EOF:数据结尾的标识,长度1字节

check_sum:校验和

11.AOF持久化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值