剖析Redis常用数据类型对应的数据结构

129 阅读3分钟

剖析Redis常用数据类型对应的数据结构

Redis:K-V,NoSQL

类型:字符串、列表、字典、集合、有序集合

列表(list)

  • 压缩列表

    • 存储数据量小
    • 列表保存单个数据小于64字节
    • 列表中数据个数小于512
  • 双向循环链表

    • 存储数据量大
    • Redis双向链表额外定义一个list结构体,组织链表首尾指针,长度等信息,使用很方便

字典(hash)

  • 压缩列表
    • 存储数据量小
    • 列表保存单个数据小于64字节
    • 列表中数据个数小于512
  • 散列表
    • MurmurHash2哈希算法运行速度快、随机性好作为哈希函数

      • 哈希冲突:链表法
    • 支持散列表动态扩容、缩容

    • 数据动态增加,装载因子不停变大,为避免散列表性能下降,装载因子大于1Redis扩容,扩为原来2倍左右,具体要计算

    • 数据动态减小,装载因子小于0.1缩容,缩小为字典中数据个数的2倍左右,具体源码

    • 扩容缩容大量数据搬移和哈希值重新计算,耗时,使用渐进式扩容缩容策略,数据搬移分批进行,避免大量数据一次性搬移导致服务停顿

集合(set)

  • 有序数组
    • 都是整数
    • 存储个数不超过512个
  • 散列表

有序集合(sortedset)

  • 数据量小:压缩列表
    • 所有数据大小小于64字节
    • 元素个数小于128

数据结构持久化

Redis经常用做内存数据库,也可以数据落盘,将内存中数据存储到硬盘。

散列表指针指向内存中存储地址,Redis如何将一个跟具体内存地址有关的数据结构存储到磁盘中?数据结构持久化,或者对象持久化问题,"持久化":"存储到磁盘"

如何将数据结构持久化到硬盘?

  • 清除原有存储结构,只将数据存储到磁盘,需要还原再重新将数据组织为原来的数据结构
    • 弊端:数据从硬盘到内存耗时,需要重新计算每个数据哈希值,如果10GB?
  • 保留原来的存储方式,将数据按照原有格式存储到磁盘,可以避免重新计算哈希值
    • 比如散列表,大小,每个数据被散列到的槽的编号都保存在磁盘,那就要耗硬盘内存了,不过也是快

思考

  1. Redis很多数据类型都是多种数据结构一起组合实现,为什么这样设计?用一种固定的数据结构不更简单吗?
    1. Redis数据结构由多种数据结构组合实现,主要出于时间和空间考虑,数据量小通过数组下标访问最快,占用内部才能最小,而压缩列表知识数组升级版
    2. 数据量大的时候需要用链表了,同时为了保证速度需要和数组结合,也就有了散列表
    3. 对于数据的大小和多少采用哪种数据结构,相信redis团队一定是根据大多数的开发场景而定的。
  2. 数据结构持久化有两种方法,对于二叉查找树我们如何将它持久化到磁盘中?
    1. 存储方式一:通过填充叶子结点形成完全二叉树,然后以数组形式存储到硬盘,数据还原也是非常高效的

数据量小采用连续内存的数据结构是为了CPU缓存读取连续内存来提高命中率,而限制数据结构数量和数据大小应该是考虑到CPU缓存的大小