redis学习系列(三-3)--redis基础类型初探(hash对象)

今天再次来记录下hash对象的存储是什么样的,hash对象在java里是比较有意思的一个东西,虽然最底层的实现我不是很懂,但是jdk源码中关于hash的一些东西我还是比较了解的,对于hash来说,主要的就是你的hash算法是怎么保证该值落到hash槽内,并且还要保证尽可能的均匀。


hash对象的编码是ziplist或者是hashtable,和列表对象一样,也使用了ziplist,这是个神奇的东西呢,,

ziplist编码

ziplist编码的hash对象使用zip列表作为底层实现,每当有新的键值对加入到hash对象时,会先将保存的键的压缩列表节点推入到列表结尾,然后再将保存了值的压缩列表节点推入到压缩列表表尾。

1. 同一键值对的两个节点在一起。

2.先保存的在头,后保存的在尾。

digraph {    label = "\n 图 8-9    ziplist 编码的 profile 哈希对象";    rankdir = LR;    node [shape = record];    redisObject [label = " redisObject | type \n REDIS_HASH | encoding \n REDIS_ENCODING_ZIPLIST | <ptr> ptr | ... "];    ziplist [label = " 压缩列表 ", width = 4.0];    redisObject:ptr -> ziplist;}

digraph {    label = "\n 图 8-10    profile 哈希对象的压缩列表底层实现";    //    node [shape = record];    ziplist [label = " zlbytes | zltail | zllen | <key1> \"name\" | <value1> \"Tom\" | <key2> \"age\" | <value2> 25 | <key3> \"career\" | <value3> \"Programmer\" | zlend "];    node [shape = plaintext];    edge [style = dashed];    kv1 [label = "第一个添加的键值对"];    kv1 -> ziplist:key1 [label = "键"];    kv1 -> ziplist:value1 [label = "值"];    kv2 [label = "第二个添加的键值对"];    kv2 -> ziplist:key2;    kv2 -> ziplist:value2;    kvN [label = "最新添加的键值对"];    kvN -> ziplist:key3;    kvN -> ziplist:value3;}

hashtable编码

底层使用字典实现,hash对象中每个键值对使用一个字典值来保存。

1.字典中的每个键都是一个字符串对象,对象中保存键

2.字典中的每个值都是一个字符串对象,对象中保存值

如果上例中不是ziplist,而是hashtable,那底层就是这样的

digraph {    label = "\n 图 8-11    hashtable 编码的 profile 哈希对象";    rankdir = LR;    //    node [shape = record];    redisObject [label = " redisObject | type \n REDIS_HASH | encoding \n REDIS_ENCODING_HT | <ptr> ptr | ... "];    dict [label = " <head> dict | <key1> StringObject \n \"age\" | <key2> StringObject \n \"career\" | <key3> StringObject \n \"name\" ", width = 1.5];    age_value [label = "StringObject \n 25"];    career_value [label = "StringObject \n \"Programmer\""];    name_value [label = "StringObject \n \"Tom\""];    //    redisObject:ptr -> dict:head;    dict:key1 -> age_value;    dict:key2 -> career_value;    dict:key3 -> name_value;}


编码转换

ziplist使用条件和列表对象一样

1.所有键值对的字符串长度都小于64字节

2.保存的键值对数量小于512个。

当然可以通过修改配置文件去改变hash-max-ziplist-value 选项和 hash-max-ziplist-entries


转换的例子不做了,跟列表对象一样。


最后贴一下实现:

表 8-9 哈希命令的实现

命令 ziplist 编码实现方法 hashtable 编码的实现方法
HSET 首先调用 ziplistPush 函数, 将键推入到压缩列表的表尾, 然后再次调用 ziplistPush 函数, 将值推入到压缩列表的表尾。 调用 dictAdd 函数, 将新节点添加到字典里面。
HGET 首先调用 ziplistFind 函数, 在压缩列表中查找指定键所对应的节点, 然后调用 ziplistNext 函数, 将指针移动到键节点旁边的值节点, 最后返回值节点。 调用 dictFind 函数, 在字典中查找给定键, 然后调用 dictGetVal 函数, 返回该键所对应的值。
HEXISTS 调用 ziplistFind 函数, 在压缩列表中查找指定键所对应的节点, 如果找到的话说明键值对存在, 没找到的话就说明键值对不存在。 调用 dictFind 函数, 在字典中查找给定键, 如果找到的话说明键值对存在, 没找到的话就说明键值对不存在。
HDEL 调用 ziplistFind 函数, 在压缩列表中查找指定键所对应的节点, 然后将相应的键节点、 以及键节点旁边的值节点都删除掉。 调用 dictDelete 函数, 将指定键所对应的键值对从字典中删除掉。
HLEN 调用 ziplistLen 函数, 取得压缩列表包含节点的总数量, 将这个数量除以 2 , 得出的结果就是压缩列表保存的键值对的数量。 调用 dictSize 函数, 返回字典包含的键值对数量, 这个数量就是哈希对象包含的键值对数量。
HGETALL 遍历整个压缩列表, 用 ziplistGet 函数返回所有键和值(都是节点)。 遍历整个字典, 用 dictGetKey 函数返回字典的键, 用 dictGetVal 函数返回字典的值。
















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值