Redis的hash类及主要指令 文章目录Redis的hash类及主要指令一、hash类特点二、内部实现三、常用命令1. HSET2. HGET3. HMGET4. HGETALL5. HDEL6. HEXISTS7. HKEYS8. HVALS9. HLEN10. HINCRBY11. HINCRBYFLOAT12. HSETNX13. HSTRLEN14. HRANDFIELD四、小结Redis的hash类及主要指令一、hash类特点hash 是一个键值对集合类似 Java 里的HashMap一个 key 下面挂着多组 field-value每个 field 都是唯一的field 可以重复写后写的值会覆盖前面的适合存对象比如用户信息、商品详情比把对象序列化成 string 存进去方便得多——想改哪个字段直接改不用整个拿出来再塞回去二、内部实现版本编码说明7.0 之前ziplist压缩列表field 和 value 交替存放在一块连续内存里省空间但读写要遍历O(n)hashtable哈希表正经的哈希表结构读写 O(1)但内存开销大7.0 及之后listpack紧凑列表替代 ziplist 的东西结构上更安全解决了 ziplist 连锁更新的问题hashtable哈希表同上大数据量时使用什么时候会从 ziplist/listpack 转成 hashtablefield 的数量超过hash-max-ziplist-entries或hash-max-listpack-entries某个 field 或 value 的长度超过hash-max-ziplist-value或hash-max-listpack-value这两个阈值都可以在配置文件中改默认值一般够用。简单来说就是数据少的时候用紧凑结构省内存数据多了自动切到哈希表保证速度。三、常用命令1. HSET往 hash 里设置 field-value。可以一次设一组也可以一次设多组。如果 field 已经存在会覆盖旧值。语法HSET key field value [field value ...]返回值新增的 field 数量覆盖旧值的不算新增示例redis HSET user name zhangsan (integer) 1 redis HSET user age 25 city beijing (integer) 2 redis HSET user name lisi (integer) 0 redis HGET user name lisi注意从 Redis 4.0 开始HSET 支持一次设置多个 field-value在此之前只能用 HMSET 做批量设置。现在 HMSET 已经算是被废弃了统一用 HSET 就行。2. HGET获取 hash 中某个 field 对应的 value。field 不存在返回 nil。语法HGET key field返回值field 对应的 value或者 nil示例redis HSET user name zhangsan age 25 (integer) 2 redis HGET user name zhangsan redis HGET user gender (nil)3. HMGET一次性获取多个 field 的值。不存在的 field 对应位置返回 nil。语法HMGET key field [field ...]返回值按顺序返回的 value 列表示例redis HSET user name zhangsan age 25 city beijing (integer) 3 redis HMGET user name age gender 1) zhangsan 2) 25 3) (nil)跟 mget 一个道理批量操作减少了网络往返次数性能比一个一个 hget 高。4. HGETALL把整个 hash 的所有 field-value 都拿出来。返回格式是 field1, value1, field2, value2 这样交替排列。语法HGETALL key返回值field 和 value 交替的列表key 不存在时返回空列表示例redis HSET user name zhangsan age 25 (integer) 2 redis HGETALL user 1) name 2) zhangsan 3) age 4) 25**⚠️ 注意**HGETALL 是一个比较重的命令。如果 hash 里的 field 特别多比如几万个一次全拿出来会阻塞 Redis还会占大量网络带宽。这种场景下建议用 HSCAN 分批拿。5. HDEL删除 hash 中指定的 field。可以一次删多个。语法HDEL key field [field ...]返回值实际删除的 field 数量不存在的 field 不算示例redis HSET user name zhangsan age 25 city beijing (integer) 3 redis HDEL user age city (integer) 2 redis HDEL user gender (integer) 0 redis HGETALL user 1) name 2) zhangsan6. HEXISTS判断 hash 中某个 field 是否存在。这个跟 string 的 EXISTS 不一样——EXISTS 是看 key 存不存在HEXISTS 是看 key 里面的 field 存不存在。语法HEXISTS key field返回值1 表示存在0 表示不存在示例redis HSET user name zhangsan (integer) 1 redis HEXISTS user name (integer) 1 redis HEXISTS user age (integer) 0 redis HEXISTS notexist name (integer) 07. HKEYS返回 hash 中所有的 field。语法HKEYS key返回值field 列表key 不存在时返回空列表示例redis HSET user name zhangsan age 25 city beijing (integer) 3 redis HKEYS user 1) name 2) age 3) city8. HVALS返回 hash 中所有的 value不返回 field。语法HVALS key返回值value 列表key 不存在时返回空列表示例redis HSET user name zhangsan age 25 city beijing (integer) 3 redis HVALS user 1) zhangsan 2) 25 3) beijing9. HLEN返回 hash 中 field 的数量。语法HLEN key返回值field 个数key 不存在时返回 0示例redis HSET user name zhangsan age 25 (integer) 2 redis HLEN user (integer) 2 redis HLEN notexist (integer) 010. HINCRBY把 hash 中某个 field 的值加上一个整数。field 不存在就当它是 0 开始加。值不是整数就报错。语法HINCRBY key field increment返回值加完后的值示例redis HSET user age 25 (integer) 1 redis HINCRBY user age 1 (integer) 26 redis HINCRBY user age -5 (integer) 21 redis HINCRBY user score 100 (integer) 100 redis HINCRBY user name 1 (error) ERR hash value is not an integer11. HINCRBYFLOAT跟 HINCRBY 一样只不过加减的是浮点数。语法HINCRBYFLOAT key field increment返回值加完后的值字符串形式示例redis HSET product price 19.9 (integer) 1 redis HINCRBYFLOAT product price 0.1 20 redis HINCRBYFLOAT product price -5.5 14.5 redis HINCRBYFLOAT product price 2.0e1 34.512. HSETNX只在 field 不存在的时候才设置值存在就不动。跟 SETNX 的思路一样。语法HSETNX key field value返回值1 表示设置了0 表示 field 已存在没设置示例redis HSET user name zhangsan (integer) 1 redis HSETNX user name lisi (integer) 0 redis HSETNX user age 25 (integer) 1 redis HGET user name zhangsan redis HGET user age 2513. HSTRLEN返回 hash 中某个 field 的 value 的字符串长度。跟 STRLEN 差不多只不过作用域是 hash 里的 field。语法HSTRLEN key field返回值value 的字符长度field 或 key 不存在返回 0示例redis HSET user name zhangsan (integer) 1 redis HSTRLEN user name (integer) 8 redis HSTRLEN user notexist (integer) 014. HRANDFIELD随机返回 hash 中的 field。可以指定返回几个还可以选择是否带 value 一起返回。语法HRANDFIELD key [count [WITHVALUES]]返回值随机 field 的列表带了 WITHVALUES 的话就是 field-value 交替返回示例redis HSET user name zhangsan age 25 city beijing (integer) 3 redis HRANDFIELD user name redis HRANDFIELD user 2 1) city 2) age redis HRANDFIELD user 2 WITHVALUES 1) age 2) 25 3) name 4) zhangsan redis HRANDFIELD user -2 1) name 2) name关于 count 参数count 为正数时返回的结果不会重复count 为负数时返回的结果可能重复count 超过 field 总数时正数只返回全部不报错负数补齐到 |count| 个有重复四、小结hash 适合存对象比 string 序列化灵活改哪个字段就操作哪个字段不用整体读写内部编码自动切换小数据用 listpack/ziplist 省内存大数据自动切 hashtable一般不用手动管HGETALL 要慎用field 太多的时候会卡大 hash 遍历用 HSCAN批量操作用 HMGET/HSET跟 string 的 mget/mset 一个道理减少网络开销计数操作用 HINCRBY直接操作 hash 里的数值字段不用先读出来再加并发场景下更安全