文章目录
- hash
- 常用命令
- hset
- hget
- hexists
- hdel
- hkeys
- hvals
- hmget
- 压缩
- hash和string
本篇总结的是,在Redis中的哈希数据类型
hash
在Redis内部本身,其实就是一种键值对的结构,而在key-value的value本身,其实也可以是一种哈希结构
而在value的哈希结构中,一般叫做是field-value结构
常用命令
hset
hset key field value [field value ...]
而在这里的value,只能是以字符串的形式出现,返回值是设置成功的数量:
127.0.0.1:6379> hset key1 f1 111
(integer) 1
127.0.0.1:6379> hset key1 f2 222 f3 333
(integer) 2
hget
这个命令只能获取单个field的值:
hget key field
具体使用:
127.0.0.1:6379> hget key1 f1
"111"
127.0.0.1:6379> hget key1 f2
"222"
127.0.0.1:6379> hget key1 f1 f2
(error) ERR wrong number of arguments for 'hget' command
hexists
判断hash中是否存在有指定的字段
时间复杂度是O(1),返回值是0表示没有,返回值是1表示存在
127.0.0.1:6379> hexists key1 f1
(integer) 1
127.0.0.1:6379> hexists key1 f100
(integer) 0
hdel
删除hash中指定的字段,del删除的是key,而hdel删除的是field
返回值也是本次操作删除的字段的个数
hdel key field [field ...]
具体事例如下:
127.0.0.1:6379> hdel key1 f1 f2
(integer) 2
hkeys
先根据key找到对应的hash,再遍历hash
127.0.0.1:6379> hkeys key1
1) "f3"
2) "f1"
3) "f2"
这个操作也是有一定的风险存在的,具体类似于之前讲过的keys *,这个操作可能会因为某个key对应的hash结构中存在大量的数据,导致最终单线程模型下的Redis被阻塞
hvals
和hkeys相对,能够获取到hash中所有的value值
127.0.0.1:6379> hkeys key1
1) "f3"
2) "f1"
3) "f2"
127.0.0.1:6379> hvals key1
1) "333"
2) "111"
3) "222"
hmget
类似于之前的mget,一次可以查询多个field
127.0.0.1:6379> hmget key f1 f2 f3
1) (nil)
2) (nil)
3) (nil)
127.0.0.1:6379> hmget key1 f1 f2 f3
1) "111"
2) "222"
3) "333"
上述的这些命令都是有一定风险的,可能会造成线程阻塞,原因在于这些命令都是要一次完成所有的操作,所以可能会阻塞Redis,那有没有其他的方法呢?
这里介绍一个命令叫做hscan,它属于是渐进式遍历,相当于是敲一次命令遍历一小部分,再敲一次,遍历一小部分,连续执行多次,就可以完成整个的遍历过程了,相当于是化整为零的操作
压缩
谈到哈希,就要先说说压缩算法了,压缩算法常见的有rar,zip,gzip,7z等等,而压缩的本质,其实就是对于数据进行重新编码,而针对于不同的数据,它们会有不同的特点,就可以依据这些不同的特点进行特定的设计,从而在编码之后,就能够达到缩小体积的效果
而这里想表述的含义是,ziplist也是如此,作为哈希的编码方式,它内部的数据结构也是精心设计的,目的就是在于要节省内存空间,对于表示一个普通的哈希表来说,可能会造成一些内存浪费的问题,比如说,hash是一个数组,而作为数组,就会导致有些地方有元素,有些地方没有元素,那么没有元素的位置其实就是一种资源的浪费,那为了解决这样的问题,就有了ziplist这种编码方式
对于这种编码方式来说,它的一个特点就是读写元素的效率会变低,速度会变慢,如果元素比较少还好,但是一旦元素达到一定的程度,此时就会导致效率明显降低,所以此时就有了另外一种编码方式叫做hashtable
总结
因此我们说:
- 哈希表的元素比较少的时候,就使用ziplist来表示,如果比较多就使用hashtable来表示
- 每个value的值长度都比较短的时候,就使用ziplist来表示,如果某个value的值太长了,就会转换成hashtable
hash和string
那么现在的问题是,为什么要使用hash?难道使用JSON进行表示string难道不可以吗?其实是可以的,但是这会面临一个问题,比如要对于数据进行修改,需要把JSON先进行序列化,然后更改数据后再进行反序列化,这样的成本显然是比直接操作hash要高的,因此才引入了hash这样的概念