• Redis 数据类型和底层数据结构的对应关系

    • image.png
  • Redis 使用一个哈希表 O(1) 保存所有键值对

    • 全局哈希表(数组)
      • image.png
    • 每个数组元素称为一个哈希桶(指针)
    • 每个哈希桶保存多个键值对数据
    • 计算键的哈希值就可以知道对应的哈希桶位置
  • 哈希冲突

    • 两个 key 的哈希值和哈希桶计算对应关系时,正好落在了同一个哈希桶中。

    • 解决方案:链式哈希。同一个哈希桶中的多个元素用一个链表来保存,它们之间依次用指针连接。

    • 当一个桶中的元素过多,访问时间变长时

      • 采用两个全局哈希表,当哈希表 1 不够大时 copy 到更大的哈希表 2

      • rehash:增加现有哈希桶的数量

        • 装载因子的大小 = 所有 entry 个数除以哈希表的哈希桶个数

        • < 1 或者在进行 RDB 和 AOF 重写时禁止 rehash

        • = 1,且允许进行 rehash 时会进行 rehash

        • = 5,立马开始 rehash

      • 渐进式 rehash(实际)

        • 每次处理请求时,顺带拷贝一部分数据到另一个哈希表。
        • 定时任务周期性地搬移一些数据到新的哈希表中
  • 压缩列表 ziplist 的结构

    • 表头

      • zlbytes:列表长度
      • zltail:列表尾的偏移量
      • zllen:entry 个数
    • 表尾 zlend:列表结束,取值默认是 255

    • 元素 entry

      • prev_len 前一个 entry 的长度

        • 1 字节:上一个 entry 的长度 < 254 字节
        • 5 字节:1 字节以外的情况
        • prev_len的第一个字节表示一个entry的开始,如果等于255表示列表结束,如果等于254那后四个字节才是prev_len的实际值,如果小于254,那就不需要后四个字节,直接使用这一个字节表示prev_len的实际值
        • 当前一节点长度大于等于254时,第一个字节为254(1111 1110)作为标志,后面4个字节组成一个整型用来存储长度
      • encoding 编码方式,1 字节

      • content 实际数据

    • 其他操作同整数数组、双向列表

      • image.png
    • 顺序查找 O(N)

  • 跳表 O(logN):多级索引,通过索引位置的几个跳转,实现数据的快速定位

  • 不同操作的复杂度

    • 单元素操作是基础

      • 每一种集合类型对单个数据实现的增删改查操作
    • 范围操作非常耗时

      • 集合类型中的遍历操作,可以返回集合中的所有数据

        • 用 SCAN 代替遍历操作
    • 统计操作通常高效

      • 集合类型中对集合中所有元素个数的记录
    • 例外情况只有几个

      • 某些数据结构的特殊记录