Redis【一】数据结构

138 阅读2分钟
  • string
  • 字典Hash
  • list
  • 集合set
  • 有序集合
  • HyperLogLog
  • Geo
  • Pub/Sub

string

get/set 场景:

  • session
  • 通常的数据缓存
  • 计数器
  • 分布式锁 底层实现: 基于SDS数据结构实现,并没有使用单纯的c语言字符串。 原因:
  1. C语言字符串取长度要遍历
  2. C语言字符串增加/减少设计重新分配
  3. 不能保存图片等二进制信息
C 字符串SDS
获取字符串长度的复杂度为 O(N) 。获取字符串长度的复杂度为 O(1) 。
API 是不安全的,可能会造成缓冲区溢出。API 是安全的,不会造成缓冲区溢出。
修改字符串长度 N 次必然需要执行 N 次内存重分配修改字符串长度 N 次最多需要执行 N 次内存重分配。
只能保存文本数据。可以保存文本或者二进制数据。
可以使用所有 <string.h> 库中的函数。可以使用一部分 <string.h> 库中的函数。

字典Hash

hget/hset/hgetall

场景:

  • 能直观,相比string更节省空间,的维护缓存信息,如用户信息,视频信息等。

rehash:

  • 没执行BGSAVE/BGSAVEAOF命令的时候,设置负载因子=1
  • 在执行BGSAVE/BGSAVEAOF命令的时候,为了避免消耗内存,提高了负载因子=5,因为在执行 BGSAVE 命令或 BGREWRITEAOF 命令的过程中, Redis 需要创建当前服务器进程的子进程, 而大多数操作系统都采用写时复制(copy-on-write)技术来优化子进程的使用效率, 所以在子进程存在期间, 服务器会提高执行扩展操作所需的负载因子, 从而尽可能地避免在子进程存在期间进行哈希表扩展操作, 这可以避免不必要的内存写入操作, 最大限度地节约内存。
  • hash函数:murmurhash2

渐进式rehash:

因为在进行渐进式 rehash 的过程中, 字典会同时使用 ht[0] 和 ht[1] 两个哈希表, 所以在渐进式 rehash 进行期间, 字典的删除(delete)、查找(find)、更新(update)等操作会在两个哈希表上进行: 比如说, 要在字典里面查找一个键的话, 程序会先在 ht[0] 里面进行查找, 如果没找到的话, 就会继续到 ht[1] 里面进行查找, 诸如此类。 另外, 在渐进式 rehash 执行期间, 新添加到字典的键值对一律会被保存到 ht[1] 里面, 而 ht[0] 则不再进行任何添加操作: 这一措施保证了 ht[0] 包含的键值对数量会只减不增, 并随着 rehash 操作的执行而最终变成空表。

有序集合

底层实现是跳跃表

redis跳跃表相关数据结构的介绍 跳表数据结构

跳跃表的增加节点、删除节点 跳跃表原理