文章目录
  1. 1. 导语

导语

Redis作为缓存也好,非关系型数据库也罢,随着版本的迭代已经越来越多的被互联网企业所使用。在我们公司也是作为一直被信赖的非关系型数据库存在着。

使用redis 一年多,第一次静心读一下《Redis设计与实现》这本书,发现里面通过redis底层设计的介绍,给了我们很多使用redis的启发,比如怎么设计key/value会更加省内存和cpu等。

这里对《Redis设计与实现》简单做的笔记,大多为摘录原书内容,原书里面有对概念的举证,理解起来很容易。


redis是用C写的,但在部分结构上也做了修改,比如:弃用c字符串并重新设计,定义为SDS(simple dynamic string)简单动态字符串的抽象类型。

SDS比之C字符串优点:
1、常熟复杂度获取字符串长度
2、杜绝缓冲区溢出
3、减少修改字符串长度时重新分配内存次数
4、二进制安全
5、兼容部分C字符串函数

Redis使用跳跃表作为有序集合建的底层实现之一

  • 跳跃表支持平均o(logN)、最坏o(N)复杂度的节点查找,还可以通过顺序性操作来批量处理节点。
  • 在大部分情况下,跳跃表效率可以跟平衡树相媲美,而且因为跳跃表实现比平衡术要来的更简单,所以有不少程序会使用跳跃表来代替平衡树。
  • Redis在两个地方用到了跳跃表,一个是实现有序集合键,另一个是在集群节点中用作内部数据结构

关于String类型保存value的两种编码

  • string类型的value控制在32字节之内,使用embstr编码效率更高,因为embstr编码只调用一次内存分配来创建redisobject和sdshdr,而raw编码则需要分别两次内存分配来分别创建。
    • 原文:raw编码会调用两次内存分配函数来分别创建redisObject和sdshdr结构,而embstr编码则通过一次内存分配函数来分配一块连续的空间依次包含redisObject和sdshdr两个结构
  • 另外embstr编码字符串是只读的,当我们对embstr编码字符串进行修改时,程序会自动将embstr编码转化为raw编码。

由此可见在做string设计时,要尽量控制value的长度,并且避免有修改操作,这样有效利用embstr编码的优势减少对内存分配释放的操作,提高效率。

redis对象共享逻辑:

  • redis对象共享的设计是一个非常给力的设计,很好的利用这点会很大程度的节省内存开支。
    简单解释就是:当redis发现(有一个对比过程,很好的利用对比过程可以减少cpu开支)某value=100的值对象在另一个key中也有value=100的值对象,拿着两个key就可以公用同一字符串值对象(详见8.9 对象共享)。特别声明的是:共享对象不单单只有字符串键可以使用,那些数据结构中嵌套了字符串对象的对象都可以使用共享对象(linkedlist编码的列表对象、hashtable编码的哈希对象和集合对象、以及zset编码的有序集合对象)
  • 对象共享优化建议,摘自原文,略缩减:
    • 一个共享对象保存的值越复杂,验证共享对象和目标对象是否相同所需的复杂度越高,消耗的cpu时间也就越多。
    • 如果共享对象保存整数值的字符串对象,那么验证复杂度为o(1),如果保存字符串值的字符串对象,那么验证复杂度为o(N)
    • 如果共享对象是保存了多个值或对象,比如列表对象或者哈希对象,那么验证复杂度为o(N2次方)

这就使我们在做redis设计时,存放的value尽量简单到整数值(0-9999的数字),会使用到一部分共享对象。
注意:Redis由于共享对象比较的复杂度,只针对0-9999的数字进行共享。

redis对象空转时常的设计:

  • LRU:LRU全称是Least Recently Used,即最近最久未使用
  • 空转时长说白了就是存储对象的空闲时间,redis为了更好的管理内存,在redisObject的lru属性中记录了存储对象最后一次被访问的时间,用OBJECT IDLETIME(OBJECT ENCODING 命令:value的编码、OBJECT REFCOUNT 命令:存值次数)命令就可以打印出key的空闲时间(当前时间-lru)。
  • 空转时长的作用就是有效管理内存,在redis配置中如果打开了maxmemory选项并且服务器回收算法为:volatile-lru或者是allkeys-lru那么当服务器内存超过maxmemory时,空转时长最大的就会被优先回收、释放。

redis类型和value编码方式:前面介绍过string的两种编码,其实每种结构,value的存储至少有两种以上编码,对于hash、集合、有序集合和列表都有一种zip压缩编码还有一种普通编码,有效的利用zip编码会大大节省内存。

  • redis共有字符串、列表、哈希、集合和有序集合5中类型对象,每种类型对象至少都有两种或以上的编码方式,不同的编码方式可以在不同的使用场景上优化使用效率。
文章目录
  1. 1. 导语