redis自身的键值对是通过哈希的方式来组织的,即key value
结构。而value也可以是哈希结构,为了和redis本身的key value
区分,采用field value
,注意这里的value是field对应的值,不是键key对应的值。
需求:存储一个uid为1的用户对象,姓名zhangsan,年龄18
使用string类型的代码“低内聚”,而使用哈希类型是”高内聚“。因为hash类型将用户的信息都存在一个value中,string类型是分别存在不同的value中。
常见命令
hset
设置hash中的field和value
语法:hset key field value [field value...]
时间复杂度:O(1)
返回值:添加的字段个数
hget
获取hash中指定字段的值
语法:hget key field
时间复杂度:O(1)
返回值:字段对应的值或nil
hexists
判断是否存在指定字段
语法:hexists key field
时间复杂度:O(1)
返回值:1表示存在,0表示不存在
hdel
删除hash中指定的字段
语法:hdel key field [field ...]
时间复杂度:O(1)
返回值:返回删除字段个数
hkeys
返回hash中所有字段
语法:hkeys key
时间复杂度: O(1)
返回值: 返回字段列表
hvals
返回hash中所有的值
语法:hvals key
时间复杂度:O(1)
返回值:返回所有的值
hgetall
获取hash中所有字段和对应的值
语法:hgetall key
时间复杂度:O(1)
返回值:返回所有的字段和对应的值
hmget
一次获取hash中多个字段的值
语法:hget key field [field...]
时间复杂度:O(1)
返回值:返回字段对应的值或者nil
hlen
获取hash中所有字段的个数
语法:hlen key
时间复杂度:O(1)
返回值:返回字段个数
hsetnx
只能在字段不存在的情况下,设置hash中的字段和值
语法:hsetnx key field value
时间复杂度:O(1)
返回值:设置成功返回1,设置失败返回0
hincrby
将hash中字段对应的数值添加指定的值
语法:hincrby key field increment
时间复杂度:O(1)
返回值:字段变化后的值
hincrbyfloat
hincrby的浮点数版本
语法:hincrbyfloat key field
时间复杂度:O(1)
返回值: 字段变化后的值
内部编码
hash的内部编码有两种
- ziplist压缩列表:当hash类型元素个数较少,同时每个value的值长度都比较短,redis使用ziplist作为hash的内部实现。ziplist使用压缩算法(压缩就是对数据进行重新编码,例如aaaaaabbbbbb重新编码成6a6b,缩小体积),节省内存空间。
- hashtable哈希表:当hash类型无法满足ziplist条件时,redis会使用hashtable作为hash的内部实现,因为ziplist读写元素需要压缩和解压缩的过程,当元素多/value值太长的时候读写速度会很慢,而hashtable的读写时间复杂度是O(1)
hash类型的应用场景
作为缓存
场景:存储结构化的数据(类似数据表这样的结构) ,如下图
使用hash存储
string类型借助json格式也能做到上述效果,但是比较麻烦。例如只想获取/修改其中某个field,需要把整个json都读取出来,解析成对象,操作field,再重写转成json字符串,再写回去。