Redis数据类型介绍
Redis不是简单的键值存储,它实际上是一个数据结构服务器,支持各种类型的值。这意味着,尽管在传统的键值存储中,你将字符串键关联到字符串值,但是在Redis中,该值不仅限于简单的字符串,还可以保存更复杂的数据结构。以下是Redis支持的所有数据结构的列表,本教程将分别进行介绍:
- 二进制安全字符串。
- 列表:根据插入顺序排序的字符串元素集合,它们基本上是链表。
- 集:唯一、未排序的字符串元素的集合。
- 排序的集,类似于集,但每个字符串元素都与一个浮点数字值(称为分数)相关联。元素总是按它们的分数排序,因此与集不同,可以检索元素的范围(例如,你可能会问:给我前10个或后10个)。
- 哈希,是由与值相关联的字段组成的映射,字段和值都是字符串,这与Ruby或Python哈希非常相似。
- 位数组(或简称为位图):可以使用特殊命令像位数组一样处理字符串值:你可以设置和清除单个位、计数所有设置为1的位、找到第一个设置或未设置的位,等等。
- HyperLogLogs:这是一种概率数据结构,用于估计集的基数,别害怕,它比看起来更简单...请参阅本教程后面的HyperLogLog部分。
- 流:仅附加的类似映射的条目的集合,提供抽象的日志数据类型。
从命令参考中掌握这些数据类型的工作方式以及如何使用它们来解决给定问题并不总是那么容易,因此,本文档是Redis数据类型及其最常见模式的速成教程。对于所有示例,我们将使用redis-cli
实用程序(一种简单但方便的命令行实用程序)针对Redis服务器发出命令。
Redis键
Redis键是二进制安全的,这意味着你可以使用任何二进制序列作为键,从“foo”之类的字符串到JPEG文件的内容,空字符串也是有效的键。
有关键的其他一些规则:
- 太长的键不是一个好主意,例如,1024字节的键不仅在内存方面是一个坏主意,而且还因为在数据集中查找键可能需要进行几次代价高昂的键比较。即使手头的任务是匹配一个大值的存在,对它进行哈希(例如使用SHA1)也是一个更好的主意,尤其是从内存和带宽的角度来看。
- 非常短的键通常不是一个好主意,如果你可以改写“user:1000:followers”,那么将“u1000flw”作为键写的就没有意义了。与键对象本身和值对象使用的空间相比,后者更具可读性,并且添加的空间较小,虽然短键显然会消耗较少的内存,但是你的工作是找到合适的平衡。
- 试着坚持一个模式,例如,“object-type:id”是一个好主意,例如“user:1000”,点或破折号通常用于多字字段,例如“comment:10000:reply.to”或“comment:10000:reply-to”中。
- 允许的最大键大小为512MB。
Redis字符串
Redis字符串类型是你可以与Redis键关联的最简单的值类型,它是Memcached中唯一的数据类型,因此对于新手来说,在Redis中使用它也是很自然的。
由于Redis键是字符串,因此当我们也使用字符串类型作为值时,我们会将一个字符串映射到另一个字符串,字符串数据类型对于许多用例很有用,例如缓存HTML片段或页面。
让我们使用redis-cli
来研究字符串类型(在本教程中,所有示例都将通过redis-cli
执行)。
> set mykey somevalue
OK
> get mykey
"somevalue"
如你所见,使用SET
和GET
命令是我们设置和检索字符串值的方式,请注意,即使键已与非字符串值相关联,SET
也会替换已存储在键中的任何现有值(即使键已存在),因此SET
执行分配。
值可以是各种类型的字符串(包括二进制数据),例如,你可以在值内存储jpeg图像,值不能大于512MB。
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
是原子的意味着什么?即使使用相同键发出INCR
的多个客户端也永远不会进入竞争状态。例如,永远不会发生客户端1读取“10”,客户端2同时读取“10”的情况,两者都递增到11,并将新值设置为11。最终值将始终为12,并且在所有其他客户端未同时执行命令时执行读取递增设置操作。
有许多用于操作字符串的命令,例如,GETSET
命令将键设置为新值,并返回旧值作为结果。你可以使用此命令,例如,如果你有一个系统,每次你的网站收到新访问者时都使用INCR
来递增Redis键,你可能希望每小时收集一次此信息,而不丢失一个增量,你可以GETSET
键,为其分配新值“0”,然后回读旧值。
在单个命令中设置或检索多个键的值的功能对于减少延迟也很有用,因此,有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表示数据库中是否存在给定的键,而DEL
命令则删除键和关联的值(无论该值是什么)。
> set mykey hello
OK
> exists mykey
(integer) 1
> del mykey
(integer) 1
> exists mykey
(integer) 0
从示例中,你还可以看到DEL
本身如何返回1或0,具体取决于键已删除(存在)或未删除(不存在具有该名称的此类键)。
有许多与键空间相关的命令,但是以上两个是必不可少的,与TYPE
命令一起使用,TYPE
命令返回存储在指定键处的值的类型:
> set mykey x
OK
> type mykey
string
> del mykey
(integer) 1
> type mykey
none
Redis expires:时间有限的键
在继续使用更复杂的数据结构之前,我们需要讨论另一个功能,该功能无论值类型如何都可以工作,并且称为Redis expires,基本上,你可以为键设置超时时间,这是有限的生存时间。生存时间过去后,该键将自动销毁,就像用户使用该键调用DEL
命令一样。
有关Redis expires的一些快速信息:
- 可以使用秒或毫秒精度进行设置。
- 但是,到期时间分辨率始终为1毫秒。
- 有关过期的信息被复制并保留在磁盘上,当你的Redis服务器保持停止状态时,时间实际上已经过去了(这意味着Redis保存了键过期的日期)。
设置过期时间很简单:
> set key some-value
OK
> expire key 5
(integer) 1
> get key (immediately)
"some-value"
> get key (after some time)
(nil)
由于第二次调用延迟了5秒钟以上,因此两次调用之间的键消失了,在上面的示例中,我们使用EXPIRE
来设置过期时间(也可以使用它来为已具有过期时间的键设置不同的过期时间,例如可以使用PERSIST
来删除过期时间并使键永久保留)。但是,我们还可以使用其他Redis命令来创建带有过期时间的键,例如,使用SET
选项:
> set key 100 ex 10
OK
> ttl key
(integer) 9
上面的示例设置了一个字符串值100的键,该键的过期时间为10秒,之后,调用TTL
命令以检查键的剩余生存时间。
为了设置并检查以毫秒为单位的过期时间,请查看PEXPIRE
和PTTL
命令以及SET
选项的完整列表。