redis底层数据结构、对象类型

数据结构:

  • 简单动态字符串SDS

    • 采用struct存储,有char []buf,len,free,O(1)的时间获取长度,空间分配自动扩容,小于1M倍增,多于1M,每次加1M。惰性删除,当字符串变短,不会缩容。
    • 二进制安全:用char []buf存储,不会过滤等处理任何存储的数据
  • 双向链表:无环、带表头和表尾指针,链表长度计数器。多态节点void *指针,可以通过dup,free,match三个属性设置类型特定函数。

  • 字典:

    • redis的字典采用hash表实现,每个字典有两个hash表,一个平时使用,一个rehash使用。
      hash冲突采用拉链法解决,被分配到同一个索引上的多个键值会连接成为单向链表。
    • 在对hash表扩容或收缩时,采用渐进式rehash完成,当发生curd时,每次增加旧hash表的索引id+1,处理这个hash到新hash上。
  • 跳跃表 skiplist:层 前进指针 跨度 后退指针 分值和成员

    • 层:包含前进指针【指向当前层的下一个节点】和跨度【span记录两个节点之间的距离】。为1到32之间的一个随机数。
    • 后退指针:用于从表尾向表头方向访问节点,每个节点只有一个后退指针,每一只能后退一个节点。
      分值:节点按分值从小到大排序。当分值相同时,按照对象大小排序。
      节点对象是一个指针,指向一个字符串对象SDS
    • 跳跃表是有序集合的底层实现之一。
  • 整数集合inset是集合键的底层实现之一。

    • 当一个集合只包含整数值元素时,并且这个集合的元素数量不多时,redis就会使用整数集合作为集合键的底层实现。包含三种编码int16_t、int32_t或者int64_t。
    • 例如当前集合元素为1、2、3,此事编码为为int16_t,当添加65536(int32_t)时,需要升级为int32_t。在原有的基础上48位扩展到128位,65536添加到最后的96-127。先移动3从原来的32-47位移动到64-95位,再移动2,最后移动1 。
    • 整数集合升级策略有两个好处,一是提升整数集合的灵活性,另一个是尽可能的节约内存。
    • 整数集合不能降级,底层实现为数组。
  • 压缩列表ziplist是列表键和哈希键的底层实现之一。

    • 压缩列表视为了节约内存而开发的顺序型数据结构。可以包含多个节点,每个节点保存一个字节数组或者整数值。
    • 每个加点包含前一个节点的长度,当前节点的编码和长度,节点内容。
    • 添加或删除节点到压缩列表,可能发生连锁更新。
    • 压缩列表结构:
      zlbytes(压缩链表的长度4字节) zltail(压缩列表表尾节点距离起始节点地址的长度4字节) zllen(节点数量,2字节,当大于65535,长度需编列才能得到) entryX(数据节点多个) zlend(特殊值OXFF,标记压缩列表末端)。

对象类型

  • String字符串对象:

    • 使用int,embstr(小于或等于39,一次分配redisObject和SDS)和raw(简单动态字符串,大于39字节,分两次分配redisObject和SDS)
    • 浮点数先转化为字符串,再存为emstr或raw。
    • 字符串对象是Redis五种类型的对象中唯一一种会被其他四种对象嵌套的对象。
  • List列表对象:

    • ziplist压缩列表 或者 linkedlist双端列表。
    • 编码转换:当列表对象保存的所有字符串元素的长度都小于64字节,列表对象保存的元素数量小于512个。不能满足这两个条件的列表对象需要使用linkedlist编码。元素小于64字节并长度小于512,采用ziplist。限制值的上限可以修改
  • Hash哈希对象:

    • ziplist或者hashtable
    • ziplist保存:每一次添加键值对,都会把键压入ziplist末尾,在把值压入ziplist,一对键值总是紧挨在一起。
    • 编码转换:哈希对象所有键值对的字符串长度小于64字节,并且哈希对象的键值对数量小于512,采用ziplist否则采用hashtable。限制值的上限可以修改。
  • Set集合对象的编码:

    • intset(整数集合)或者hashtable
    • hashtable存储集合对象,使用字典作为底层实现,字典的每一个键都是一个字符串对象,每个字符串对象包含一个集合元素,而字典的值则全部被设置为NULL。
    • 编码转换:集合对象保存所有元素都是整数值并且保存的元素数量不超过512个,采用intset编码,否则采用hashtable编码。
  • zset有序对象集合:

    • ziplist或者skiplist
    • ziplist编码的有序集合对象使用压缩列表作为底层实现,每个集合使用紧挨在一起的压缩列表节点来保存,第一节点为元素的成员,第二个节点保存分值。按分值小道大排序。
    • skiplist编码的有序对象(跳表和字典):在ziplist中按分值从小到大保存了所有的集合元素。通过这个跳跃表,程序可以对有序结合进行范围性操作。初次之外,还用dict字典为有序结合创建一个从成员到分值的映射,通过这个映射,ZSCORE可以在O(1)时间复杂度内查找成员的分值。
    • 编码转换:元素小于128个并且元素成员长度都小于64字节,采用ziplist,否则采用跳表。

过期策略

  • redis过期策略:惰性删除和定期删除相结合。
    • 惰性删除,读写数据之前都会检查此字段,过期则删除。
    • 定期删除:redis定时分多次遍历服务器中的各个数据库,随机检查一部分键是否过期,并删除其中的过期键。
  • 我会在低用户访问时采用scan扫描redis,删除过期键,释放空间。

持久化:

  • RDB:SAVE命令由服务器进程执行,会阻塞服务器。BGSAVE由子进程执行保存操作,不会阻塞服务器。
  • AOF:保存所有修改数据库的写命令请求来记录数据库状态。命令请求会保存在AOF缓冲区里面,之后再定期写入并同步到AOF文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值