哈希表应用
1 基本概念
键值关系对
"key1": {
"field1": "value1",
"field2": "value2",
"field3": "value3"
}
2 存储原理
哈希数据结构底层有两种实现方式
ziplist
压缩列表hashtable
哈希表
2.1 ziplist
压缩列表
哈希表首选的存储方式,满足以下条件会优先使用这个方式:
hash-max-ziplist-entries
表示的元素个数小于512(默认)- 且所有值(不是累加,也不是健,就是值)
hash-max-ziplist-value
小于64B(默认)
2.1.1 ziplist
数据结构
ziplist
数据结构是数组
<zlbytes><zltail><zllen><entry><entry>...<entry><zlend>
哈希表中的每个field,value
都是一个entry
,field
后面紧跟的就是value
。
查找过程就是遍历数组的过程,从第一个entry
开始查找field
,然后根据field entry
中的长度header
,找到value
位置。
2.1.2 复杂度
O(N*M)
,N
是哈希表中field
的个数,M
是请求的field
个数。
数据结构是field1 value1 field2 value2
,遍历时直接跳跃式的遍历查找field
,因此遍历的元素数量是field
的数量
2.2 hashtable
哈希表
- 不满足
ziplist
的情况下,Redis自动使用哈希表
2.2.1 复杂度
O(M)
,M
是请求的field
个数
2.3 压缩列表与哈希表对比
No | 压缩表 | 哈希表 |
---|---|---|
数据结构 | 线性存储方式,数组 | 键值对,稀疏型 |
3 哈希表应用案例
3.1 hmset/hmget
应用
设定一个key,然后将多个field-value
(字段-值)对设置到哈希表中,类似结构
{
"key1": {
"field1": "value1",
"field2": "value2",
"field3": "value3"
},
"key2": {
"field1": "value1",
"field2": "value2",
"field3": "value3"
}
}
3.1.1 hmset
特点:
- 覆盖已经存在的字段
- 哈希表不存在,则会自动创建
- redis中的字段顺序,与实际插入顺序不一致
3.1.2 hmget
特点:
- 指定字段不存在,会返回
nil
- 表值的排列顺序和指定字段的请求顺序一样
3.1.3 实践案例
整体数据结构如下:
{"baidu":{"a1":"b1","a2":"b2","a3":"b3"}}
{"google":{"a1":"b1","a2":"b2","a3":"b3"}}
字典如下:
d1 = {"a1":"b1","a2":"b2","a3":"b3"}
d2 = {"a1":"b1","a2":"b2","a3":"b3"}
1. conn.hmset("baidu", d1)
2. conn.hmget("baidu", "a1") //返回结果['b1']
3. conn.hmget("baidu", ["a1"]) //返回结果['b1']
4. conn.hmget("baidu", ["a1","a2"]) //返回结果['b1','b2']
5. conn.hmget("baidu", ["a1","a2","a3"]) //返回结果['b1','b2','b3']
引用
- redis内存分析工具
- https://neway6655.github.io/redis/2016/07/19/redis-memory-optimization-in-practice.html
- https://redisbook1e-gallery.readthedocs.io/en/latest/index.html