文章目录
注意个问题
Hash中也有映射关系,Redis本身也有映射关系:key-value。为了区分,hash中的映射关系是:
field-value,也就是说,哈希表中相当于有两层映射关系:key {field-value}
hset命令(核心)
hset key field value [field value …]
返回值是设置成功的键值对(field-value)个数。
这里的value是一个string类型。
时间复杂度O(N),N是成功插入的键值对的个数。
注意:hmset命令也可以,就是一次插入多个键值对。
hget命令(核心)
hget key field
返回值是获取到的key对应的值field对应的value值。
如果不存在,返回nil
相当于进行了两次哈希。
时间复杂度O(1)
注意:hmget同理,可以一次获取多个field对应的value值。
hexists命令
判断key对应的field对应的value是否存在。
hexists key field
返回值:1表示存在,0表示不存在。
hdel命令
删除指定的key对应的field,可以一次删除多个field
hdel key field [field … ]
返回值是成功删除的field-value个数。
注意:hdel和del是有区别的,hdel删的是一个或者多个键值对,而del命令是一股脑直接把key对应的整个哈希表都删了
hkeys和hvals命令
这个命令相当于keys命令(获取的是key)。
hkeys key
返回值是返回key对应的整个哈希表中的field。
hvals命令是获取key对应的哈希表中每个field对应的所有values。
hvals key
返回值是返回key对应的整个哈希表中的field对应的整个values字段。
注意
1.这两个操作是存在风险的,类似于keys 星
2.h系列里面的命令,必须保证key对应的value是哈希类型的。
hgetall和hmget命令
hgetall命令是获取key对应的所有的filed-value。
hgetall key
返回值是key对应的整个哈希表的键值对。
hmget命令前面说过了,类似于mget命令。
hlen命令
获取key对应的哈希表的字段元素个数
hlen key
返回值就是哈希表的字段个数。
O(1)的时间复杂度,不需要遍历。
hsetnx命令
类似于setnx命令,不存在才能设置成功,存在则设置失败。
hsetnx key field value
hincrby命令
类似于incrby命令,hash这里的value也可以当做数字来处理(前面说value是string类型)
不过这里的hincrby可以用来加减整数。
hincrby key field increment
所以value必须是整数才行。
hincrbyfloat,类似于incrbyfloat命令。
用来加减浮点数。
hincrby key field increment
哈希命令小结
哈希编码方式
hashtable的编码方式有两种:
- 1.ziplist(压缩列表,这个之前的文章讲过什么是ziplist):当哈希类型元素个数小于hash-max-ziplist-entries 配置(默认 512 个)、
同时所有值都小于hash-max-ziplist-value 配置(默认 64 字节)时,Redis 会使⽤ ziplist 作为哈
希的内部实现,ziplist 使⽤更加紧凑的结构实现多个元素的连续存储,所以在节省内存⽅⾯⽐
hashtable 更加优秀。
压缩的本质,是对数据进行重新编码。结合不同数据的特点经过巧妙设计,重新编码后,就能够缩小体积。
所以ziplist同理,内部的数据结构也是精心设计的,目的就是为了节省空间。
- 2.hashtable(哈希表):当哈希类型⽆法满⾜ ziplist 的条件时,Redis 会使⽤ hashtable 作为哈希的内部实现,这表示的是一个普通的哈希表,(hash首先是一个数组,数组上有些位置有元素,有些没有,所以可能会浪费一定空间)因为此时 ziplist 的读写效率会下降,⽽ hashtable 的读写时间复杂度为 O(1)。
付出的代价:
ziplist:(本质上就是一个双向链表),所以读写操作的代价都比较大,最坏情况可能是O(n)。
hashtable:可能会浪费一些空间。
使用到ziplist也有一些条件:
- 1.如果哈希表中的元素较少,使用ziplist。否则使用hashtable。
- 2.如果哈希表中的field对应的value值的长度较短,使用ziplist。否则value的长度太大的话,会选择使用hashtable。
使用场景
1.关系型数据表保存用户的信息
使用哈希类型进行用户属性和用户id的映射伪代码:
但是需要注意的是哈希类型和关系型数据库有两点不同之处:
• 哈希类型是稀疏的,⽽关系型数据库是完全结构化的,例如哈希类型每个键可以有不同的 field,⽽
关系型数据库⼀旦添加新的列,所有⾏都要为其设置值,即使为 null。
• 关系数据库可以做复杂的关系查询,⽽ Redis 去模拟关系型复杂查询,例如联表查询、聚合查询等
基本不可能,维护成本⾼。
关系型数据库和非关系型数据库的对比:
上面是关系型数据库,下面是非关系型数据库。
Redis三种缓存方式对比
1.原生字符串类型
这样就把同一个数据各个属性分散开了,且内存占用较大,实际上基本不使用。(低内聚)
2.JSON串
如果使用string(json)的类型来表示UserInfo(用户信息),万一只想获取某个用户的field,或者修改某个用户的field,就需要把用户整个json读出来,解析成对象,操作field,再把整个field重新写成json串的格式,再写回去。
优点:空间利用率高。
3.哈希类型(经常用这种)
如果使用hash的方式来表示UserInfo,就可以使用field表示对象的每个属性(数据表的列)此时就可以非常方便地修改/获取任何一个属性的值了。
缺点:上面讲过了,用哈希来表示UserInfo虽然读写上更直观高效,但是付出的是空间的代价。
我理解的高内聚和低耦合
我认为高内聚就是把所有关联的东西放到一起,最好能放到一个指定的地方。
这样做就是为了好找。
而低耦合就是两块代码之间的的关系不大,一个代码出bug了,另一个代码几乎没影响。