Redis并不是简单的键值对存储,事实上,Redis支持各种数据类型。下列类型会在本章讨论:
- strings:二进制安全字符串。
- Lists:一种安插入顺序记录的字符串元素集合,类似链表结构。
- Sets:无序集合,保存不重复的字符串元素。
- Sorted sets:类似Sets,但每个元素关联一个浮点数,称为score。集合内元素保证按score排序,因此可以支持根据排序获取前10个或后10个元素。
- Hashes:哈希表记录一组键值对,键值都是字符串,类似Ruby或Python哈希表。
- 位数组 (也叫位图表): 可以将字符串视作位数组进行操作。例如:可以设置或清理单个bit位,统计bit位为1的位数量,查找第一个1bit位置等操作。
- HyperLogLogs: 一个概率数据结构,用于快速方便的预测集合的基数。
- Streams: 一个只能追加元素的日志数据结构。
Redis键
Redis键是二进制安全的,也就是说可以用任何二进制数据作为Redis键,比如字符串“foo”或者一个JEPG文件。空字符串也是有效的Redis键。
其他的注意事项包括:
- 不推荐太长的Redis键,例如:1024字节的键内容既浪费内存,也耗费计算资源,如果键内容较多,建议首先计算HASH值(SHA1),再作为Redis键存储。
- 避免太短的Redis键。例如:不建议用"u1000flw" 替换 "user:1000:followers"。因为后者可读性更好,且并无明显开销。键设计需要平衡可读性和内存占用。
- 推荐通过统一分隔符定义键格式,例如:"comment:1234:reply.to" 或者 "comment:1234:reply-to"。
- Redis键最大长度为512MB。
Redis字符串
Redis字符串是一种简单的值数据,可以关联到Redis键。在Memcached中,是唯一支持的数据类型,也是Redis新手很容易理解的类型。因为Redis键是字符串,当使用字符串作为值时,其实我们关联了两个字符串。这种字符串类型通常可以被用于缓存HTML片段或页面。字符串类型可以存储任何二进制数据, 例如:jpeg图像。字符串不能超过512 MB大小。
示例:
> set mykey somevalue
OK
> get mykey
"somevalue"
正如你看到的,SET 和 GET 可用于设置和获取字符串值。需要注意的是即便之前Redis键保存的值不是字符串类型,SET也会替换Redis键对应的值。所以SET可以被看做赋值操作。
SET 可以通过额外的参数支持有趣的操作选项。例如:可以要求SET在键已存在时返回操作失败,或者相反,只在键存在时成功。
> set mykey newval nx
(nil)
> set mykey newval xx
OK
即便字符串只是基本Redis值类型, 仍然仍然实现了一些有趣的操作,例如:原子递增。
> set counter 100
OK
> incr counter
(integer) 101
> incr counter
(integer) 102
> incrby counter 50
(integer) 152
INCR 命令可以将字符串视作整数,对其做加1操作,并保存到原值。类似的操作还包括:INCRBY, DECR 和DECRBY。在内部,这些命令功能类似,只是逻辑稍有不同。
那么INCR的原子性又是指什么呢?你可以理解成多个客户同时向同一个Redis键内容发起INCR命令时,并不存在相互竞争。比如说:对于同一个Redis键,client 1 读取到"10"的同时client 2 也读取到"10",两个client同时发起INCR,使得新的键值为11的可能性并不存在。也就是说,操作结果只能是12,因为Redis会保证一个client自增操作时,其他client对此Redis键的操作不会同时进行。
字符串类型还支持很多其他操作。例如:GETSET 设置新值的同时, 将旧值作为返回结果。你可以在通过INCR 命令统计网站访客数量时使用这个命令。你也许需要每小时统计一次数量,但不想丢失一个访客数量统计。这种情况下,你可以GETSETRedis统计键, 将新值设置为"0",并获取之前的统计值作为上一小时的统计数量。
可以在一条命令里同时设置或获取多个Redis键值的操作也可以显著降低操作延时。 你可以使用 MSET 和MGET 命令实现这个效果:
> mset a 10 b 20 c 30
OK
> mget a b c
1) "10"
2) "20"
3) "30"
当使用MGET时,Redis返回值数组。
键空间命令
有些命令不限于特定数据类型,这些命令可以实现一些键空间的交互操作,可以在任何数据类型上使用。例如:EXISTS 命令通过返回1或0来表示给定Redis键在数据库中是否存在,DEL命令可以删除任何类型的键值对。
> set mykey hello
OK
> exists mykey
(integer) 1
> del mykey
(integer) 1
> exists mykey
(integer) 0
上面的示例中,你可以看到 DEL也返回1或0来表示Redis键是否成功移除,删除前已存在返回1,否则返回0。
Redis支持各种键空间相关命令,但上面两个是基础命令。和他们一样常见的TYPE命令,可以返回值对应的数据类型。
> set mykey x
OK
> type mykey
string
> del mykey
(integer) 1
> type mykey
none
Redis超时: 有限生存期的Redis键
在继续探讨更复杂的数据结构前,我们需要了解另一个与数据类型无关的Redis特性,成为Redis 超时。一般来说你可以为Redis键设置一个超时时间,来表示它的生存周期。超时后,Redis键值将自动销毁,效果类似执行DEL 命令。
以下简要说明Redis 超时:
- 支持设置秒或毫秒作为计时单位。
- 超时最终精确到毫秒精度。
- 超时信息会持久到磁盘,即便Redis停机仍保持计时。 (Redis通过记录键过期时间实现此效果)。
设置超时十分简单,且开销很小:
> set key some-value
OK
> expire key 5
(integer) 1
> get key (immediately)
"some-value"
> get key (after some time)
(nil)
两次GET 操作之间Redis键因5秒超时自动消失。
在上面示例中,我们用EXPIRE 命令设置超时。(这个命令还能在已经存在超时时间的Redis键上实现变更超时时间。类似的PERSIST 命令可以撤销超时营销,使Redis键值长期保存). 我们也可以在Redis键创建时指定超时,通过启用SET 选项实现:
> set key 100 ex 10
OK
> ttl key
(integer) 9
上面示例中,字符串被设置为100
,10秒超时。之后的TTL 命令用来检测剩余的存活时间。
网友评论