Redis数据结构 | 青训营笔记

160 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天

String

  • 可以存储字符串,数字,二进制数据
  • 通常与expire配合使用
  • 场景:存储计数、Session

数据结构sds

sds: Simple dynamic string

sdshdr: Simple dynamic string header

sdshdr由len, alloc, flag, buf四部分组成。

  • len是这符串长度
  • alloc是已申请内存大小
  • flag高8位保留未使用,低3侠表示sdshdr的类型
  • buf存储字符串的值

sds的一个char类型的指针,指向buf。sds指针左移可以查询字符串的元信息,右移可以获取字符串的值。

sds支持扩容。向字符串后面拼接一个字符串,如果拼接后的字符串长度小于alloc,则无需扩容,直接将拼接后的字符串存储在buf中,并修改len的值。如果容量不够则进行扩容,新增后长度小于1MB,则按新长度的两位扩容,大于1MB,则按新长度加上1MB扩容。

sds的优势

  • O(1)时间复杂度获取字符串长度
  • 二进制安全
  • 拥有自动扩容机制
  • 拥有惰性空间释放机制,减少了内在重分配次数

List

redis的list支持从左右两端添加和删除元素,也支持通过索引查询。

数据结构quicklist

quicklist是一个双向链表,链表的每个节点是一个listpack,一个listpack存储list中的多个元素。

listpack的结构:

  1. tot_bytes 32位, listpack的总字节数
  2. num_elements 16位,listpack存储的元素个数,若num_elements=65535则元素个数为未知,需要全部扫描。
  3. element-1,element-2,..., 变长
  4. listpack-end-byte 8位,结束标志,固定为255

element的结构:

  1. encoding-type 变长,编码类型和data长度
  2. encoding-data 实际数据
  3. element-tot-len 总长度,从右往左遍历时使用

Hash

hash_table有size个槽位,每个槽位拉出一个链表。如果hash_table元素过多,会导致查询缓慢,需要进行rehash

  • rehash

将哈希表ht[0]中的数据,全部迁移到新的哈希表ht[1]中。数据量较小的情况下速度是比较快的,但数据量大时,会明显阻塞用户的请求。

  • 渐进式rehash

每次用户访问时迁移少量数据,将整个迁移过程平摊到所有访问过程中。