Redis是采用字典结构以键值对的形式存储数据的,而散列类型(hash)的键值也是一种字典结构,其存储了字段和字段值的映射,但字段值只能是字符串,不支持其他数据类型,也就是说,散列类型不能嵌套其他的数据类型。一个散列类型键可以包含至多2^32-1个字段。
除了散列类型,Redis的其他数据类型同样不支持数据类型嵌套。比如集合类型的每个元素只能是字符串,不能是一个集合或者散列表等。
散列类型适合存储对象:使用对象类别和ID构成建名,使用字段表示对象的属性,而字段值存储属性值。例如要存储ID为2的汽车对象,可以分别使用名为color、name和price的三个字段来存储该汽车的颜色、名称和价格。
在关系型数据库中,数据是以二维表形式存储的,这就要求所有的记录都拥有同样的属性,无法单独为某条记录增减属性,如果ID为1的汽车要增加生产日期的属性,那么就需要把数据表所有的汽车增加生产日期的属性,而对于那些不需要知道生产日期的汽车来说,生产日期是冗余的。可想而知,当不同的记录需要不同的属性时,表的字段数量越来越多以至于很难维护。当使用ORM(Object-Relational Mapping,对象关系映射)将数据库中的对象实体映射成程序中的实体时,修改表的结构往往意味着终端服务(重启程序),为了防止这些问题,在关系数据库中存储这种半结构化的数据还需要额外的与之关联的表才行。
而Redis的散列类型不在这个问题,虽然图中描述了汽车对象的存储结构,但是这个结构只是人为的约定,Redis并不要求每个键都依据此结构存储,我们完全可以自由地为任何键增减字段而不影响其他键。
1. 赋值与取值
127.0.0.1:6379> HSET car price 500
(integer) 1
127.0.0.1:6379> HSET car name BMW
(integer) 1
127.0.0.1:6379> HGET car name
"BMW"
HSET命令的方便之处在于不区分插入和更新操作,这意味着修改数据时不用事先判断字段是否存在来决定执行的是插入操作还是更新操作。当执行的是插入操作时,
HSET命令返回的是1,当执行的是更新操作时,
HSET返回的是0.
127.0.0.1:6379> HMGET car price name
1) "500"
2) "BMW"
127.0.0.1:6379> HGETALL car
1) "price"
2) "500"
3) "name"
4) "BMW"
2. 判断字段是否存在
HEXISTS命令用来判断一个字段是否存在,如果存在则返回1,否则返回0
127.0.0.1:6379> HEXISTS car model1
(integer) 0
127.0.0.1:6379> HSET car model1 C200
(integer) 1
127.0.0.1:6379> HEXISTS car model1
(integer) 1
3. 字段不存在时赋值
4. 增加数字
127.0.0.1:6379> HINCRBY person score 60
(integer) 60
127.0.0.1:6379> HINCRBY person score -2
(integer) 58
之前person键不存在,HINCRBY命令会自动建立该键并默认score字段在执行命令前的键值为0,命令返回增值后的字段值。
5. 删除字段
127.0.0.1:6379> HDEL car price
(integer) 1
127.0.0.1:6379> HDEL car price
(integer) 0
6. 值获取字段名/字段值/字段数量
HVALS key : 只获取字段值
HLEN key : 只获取字段数量
127.0.0.1:6379> HKEYS car
1) "name"
2) "model1"
127.0.0.1:6379> HVALS car
1) "BMW"
2) "C200"
127.0.0.1:6379> HLEN car
(integer) 2