hash.
Redis 自身就是键值对结构
Redis 自身的键值对结构就是通过 哈希 的方式来组织的
哈希类型中的映射关系通常称为 field-value,用于区分 Redis 整体的键值对(key-value),注意这里的 value 是指 field 对应的值,不是键(key)对应的值,注意 value 在不同上下文的作用
常见命令
1)hset
设置 hash 中指定的字段(field)的值(value)
hset key field value
返回设置成功的(field-value)个数 O(N)(N field的个数)
2)hget
获取 hash 中指定字段的值
hget key field
返回字段对应的值或者nil O(1)
3)hdel
删除 hash 中指定的字段
hdel key field [field ...]
返回删除的字段的个数 O(N) (N 字段的个数)
del 删除 key hdel 删除 field
4)hkeys
根据 key 找到对应的 hash,再遍历 hash (获取 hash 中所有的字段)
hkeys key
返回字段列表 O(N) (N 字段的个数)
5)hvals
获取 hash 中所有的 value
hvals key
返回 hash 中的所有值 O(N) (N field的个数)
6)hgetall
获取 hash 中所有的字段以及对应的值
hgetall key
返回所有字段和对应的值 O(N) (N field的个数)
7)hmget
hmget key field [field ...]
返回字段对应的值或者nil O(N)(N 查询元素的个数)

在使用 HGETALL 时,如果哈希元素个数比较多,会存在阻塞 Redis 的可能。如果开发人员只需要获取部分 field,可以使用 HMGET,如果⼀定要获取全部 field,可以尝试使用 HSCAN 命令,该命令采用渐进式遍历哈希类型敲一次命令,遍历一小部分,连续执行多次就可以完成整个的遍历过程(类似于哈希表的扩容)
8)hlen
获取 hash 中所有字段的个数(不需要遍历)
hlen key
返回所有字段个数 O(1)
9)hsetnx
在字段不存在的情况下,设置 hash 中的字段和值
hsetnx key field [field ...]
返回 1表示设置成功,0 表示设置失败 O(1)
10)hincrby
hincrby key field increment(可以是负数)
返回字段加减后的值 O(1)
11)hincrbyfloat
hincrbyfloat key field increment
返回字段加减后的值 O(1)
编码方式
哈希的内部编码有两种:
1. ziplist(压缩列表)
压缩的本质是针对数据进行重新编码(节省内存空间)
不同的数据有不同的特点,根据这些特点进行设计后。重新编码之后,就能够缩小体积
2. hashtable(哈希表)
hash 首先是一个数组,数组上有些位置没有元素,浪费空间
ziplist 进行读写操作的速度比较慢,节省空间
hashtable 的读写时间复杂度为 O(1)
哈希表中的元素个数比较少,用 ziplist 表示,元素个数比较多,用 hashtable 表示
每个 value 的值长度都比较短,用 ziplist 表示,某个 value 比较长,会转换成 hashtable
在 redis.conf 文件中:
hash-max-ziplist-entries 配置(默认512个)
hash-max-ziplist-value 配置(默认64字节)
应用场景
作为缓存
string 也是可以作为缓存使用
存储结构化的数据使用 hash 比较合适(类似于数据库,表结构)
相比于使用 JSON 格式的字符串缓存信息,哈希类型更加直观,并且在操作上更加灵活
如果使用 JSON 的格式表示 UserInfo
如果执行使用其中的某个 field 或者修改某个 field
需要把整个 JSON 都读出来,解析成对象,操作 field ,再重写成 JSON 字符串写回去
如果使用 hash 的方式来表示 UserInfo —— 空间消耗大
可以使用 field 来表示对象的每个属性(数据的每个列)
可以方便的修改/获取任何一个属性
原生字符串类型 —— 使用字符串类型,每个属性一个键 ——低内聚
相当于是把同一个数据的各个属性,给分散开表示
缓存方式对比总结:
1.原生字符串 —— 使用字符串类型,每个属性一个键
优点:实现简单,针对个别属性变更也很灵活。缺点:占用过多的键,内存占用量较大,同时用户信息在 Redis 中比较分散,缺少内聚性,所以这种方案基本没有实用性2.序列化字符串,例如 JSON
优点:针对总是以整体作为操作的信息⽐较合适,编程也简单。同时,如果序列化方案选择 合适,内存的使用效率很缺点:本⾝序列化和反序列需要⼀定开销,同时如果总是操作个别属性则非常不灵活3.哈希类型
优点:简单、直观、灵活。尤其是针对信息的局部变更或者获取操作缺点:需要控制哈希在 ziplist 和 hashtable 两种内部编码的转换,可能会造成内存的较大消 耗
1)哈希类型是比较稀疏的,关系型数据库时完全结构化的
哈希类型每个键可以有不同 field ,关系型数据库添加新的列,所有行都要为其设置值
2)关系型数据库可以做复杂的关系查询,Redis 模仿关系型复杂查询较难实现(联合查询,聚合查询 ...)