redis数据结构
String
一个键最大能存储512MB
List
双向链表
- 最新消息排行
- 消息队列
注意它是链表而不是数组。这意味着 list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为 O(n)
用途
用来做异步队列
- 将需要
延后
处理的任务结构体序列化(JSON)
成字符串塞进 Redis 的列表 - 另一个线程从这个列表中轮询数据进行处理。
lpush
+lpop
= stack 先进后出的栈lpush
+rpop
= queue 先进先出的队列lpush
+ltrim
= capped collection 有限集合lpush
+brpop
= message queue 消息队列
问题
Redis 队列绕不开的消息丢失
问题
一般借助List来实现消息队列:
- 通过命令LPUSH(BLPUSH)把消息入队
- 通过命令RPOP(BRPOP)获取消息。
但这种方式实现的队列是不安全
的。
因为RPOP(BRPOP)命令的特性:
移除
list的队尾元素(消息)并返回给客户端。这时该元素只存在
于客户端的上下文中,redis服务器中没有
这个元素.- 如果客户端在处理元素的过程
崩溃
了,那么这个元素就永远丢失了。这种情况导致:客户端虽然成功收到了消息,但是却没有处理它
。
解决
那怎么来实现一个更安全的队列呢? 可以试试redis的RPOPLPUSH
(或者其阻塞版本的 BRPOPLPUSH
)命令。
具体是操作是:
- 在A队列推出元素(并删除)时,保存元素到 B队列。
- 如果处理 元素 的客户端奔溃了,还可以在B队列找到
Hash
场景
Redis 的 Hash 结构可以像在数据库中Update一个属性一样只修改某一项属性值,否则将dict序列化后存储为一个字符串的值,当作String使用
实现
比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht
创建空白哈希表时, 程序默认使用 REDIS_ENCODING_ZIPLIST
编码, 当以下任何一个条件被满足时, 程序将编码从 REDIS_ENCODING_ZIPLIST
切换为 REDIS_ENCODING_HT
:
- 哈希表中某个键或某个值的长度大于
server.hash_max_ziplist_value
(默认值为64
)。 - 压缩列表中的节点数量大于
server.hash_max_ziplist_entries
(默认值为512
)。
压缩列表编码的哈希表
当使用 REDIS_ENCODING_ZIPLIST
编码哈希表时, 程序通过将键和值一同推入压缩列表, 从而形成保存哈希表所需的键-值对结构:
+---------+------+------+------+------+------+------+------+------+---------+
| ZIPLIST | | | | | | | | | ZIPLIST |
| ENTRY | key1 | val1 | key2 | val2 | ... | ... | keyN | valN | ENTRY |
| HEAD | | | | | | | | | END |
+---------+------+------+------+------+------+------+------+------+---------+
新添加的 key-value 对会被添加到压缩列表的表尾。
当进行查找/删除或更新操作时,程序先定位到键的位置,然后再通过对键的位置来定位值的位置。
字典编码的哈希表
当哈希表使用字典编码(REDIS_ENCODING_HT
)时, 程序将哈希表的键(key)保存为字典的键, 将哈希表的值(value)保存为字典的值。
哈希表所使用的字典的键和值都是字符串对象。
下图展示了一个包含三个键值对的哈希表:
哈希冲突
链接法(separate chaining)
Set
set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的
Sorted Set
Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率
参考
https://juejin.im/post/5df77d8bf265da33f718b654
https://redisbook.readthedocs.io/en/latest/datatype/hash.html