Redis 常用数据类型及操作命令(CRUD)
相关资源:
- An introduction to Redis data types and abstractions
- Data types
- Command reference
- Redis 官方文档中文翻译(部分内容不是最新)
本文只列出了 Redis 中常用的一些命令,完整命令列表请阅读官方文档。
Redis 数据类型
Redis 不是一个简单的键值存储,它实际上是一个数据结构服务器,支持不同类型的值。这意味着,在传统的键值存储中,您可以将字符串键与字符串值相关联,而在 Redis 中,该值不仅限于简单的字符串,还可以保存更复杂的数据结构。以下是 Redis 中支持的所有数据结构的列表:
类型 | 说明 |
---|---|
Strings | 字符串 |
Lists | 列表,根据插入顺序排序的字符串元素的集合。它们基本上是链表。 |
Hashes | 哈希/散列,是由与值相关联的字段组成的映射。字段和值都是字符串。这与 Ruby 或 Python 哈希非常相似。类似于 JavaScript 中的对象结构。注意:不能嵌套。 |
Sets | 集合,唯一的、未排序的字符串元素的集合,集合中的数据是不重复的。 |
Sorted sets | 有序集合/排序集,与 Sets 类似,但每个字符串元素都与一个称为 score(分数)的浮点值相关联。元素总是按分数排序,因此与 Sets 不同,可以检索一系列元素(例如,您可能会问:给我前 10 个或后 10 个)。 |
Bit arrays(或 bitmaps) | 可以使用特殊命令像处理位数组一样处理字符串值:您可以设置和清除单个位,将所有设置为 1 的位计数,找到第一个设置或未设置的位,依此类推。 |
HyperLogLogs | 这是一种概率数据结构,用于估计集合的基数。 |
Streams | 提供抽象日志数据类型的类似映射项的仅追加集合。 |
下面将仅介绍常用的 Strings、Hashes、Sets、Sorted sets 类型。
Redis 中的键(keys)
Redis keys 是二进制安全的,这意味着您可以使用任何二进制序列作为 key,从 "foo"
之类的字符串到 JPEG 文件的内容。空字符串也是有效的键。
关于键的其他一些规则:
- 太长不好
- 占用内存空间
- 查找 key 时进行 key 比较代价太高
- 如果必须要匹配一个较大的值,最好对其进行散列(hashing,例如使用 SHA1)
- 太短也不好
- 没有可读性
- 例如,没有必要将
user.1000.followers
改为u1000flw
- 尝试坚持使用固定规则
- 例如:
object-type:id
格式,如user.1000
- 点或破折号通常用于多单词字段,如:
comment:1234:reply.to
或comment:1234:reply-to
- 例如:
- 允许的最大大小为 512 MB
数据类型 - 字符串 Strings
字符串是 Redis 中最基本的数据类型,也是其他数据类型的基础。
- 它能存储任何形式的字符串,包括二进制数据。
- 你可以用它存储用户的邮箱、JSON 化的对象,甚至是一张图片
- value 最多可以存储数据大小为 512 MB
字符串类型是其他常见 4 种数据类型的基础,其他数据类型和字符串类型的差别从某种角度来说只是组织字符的形式不同。
例如,列表类型是以列表的形式组织字符串,而集合类型是以集合的形式组织字符串。
添加
打开命令行交互工具 redis-cli
。
# 如果 key 不存在则创建,如果存在则赋值
SET key value
# 例如: 键/值不用加引号,默认就是字符串类型
# SET foo bar
# OK
# 将给定 key 的值设为 value,并返回 key 的旧值
GETSET key value
# GETSET foo baz
# bar
# 只有在 key 不存在时设置 key 的值
SETNX key value
# 同时设置一个或多个 key-value 对
MSET key value [key value ...]
# 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在时才会执行成功
MSETNX key value [key value ...]
# 如果 key 已经存在,并且值是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值的末尾,如果 key 不存在,则添加
APPEND key value
注意:
- 键/值不用加引号,默认就是字符串类型
- 在 Redis 命令中不区分大小写,也就是说
SET foo bar
和set foo bar
是一样的,但是我们约定使用大写表示一个 Redis 命令。
查询
# 获取指定 key 的值
GET key
# 返回 key 中字符串值的子字符
GETRANGE key start end
# 获取所有(一个或多个)给定 key 的值
MGET key [key ...]
# 返回 key 所存储的字符串值的长度
STRLEN key
# 通用命令: 查询字典中是否有指定的 key(返回匹配的个数)
EXISTS key [key ...]
# 通用命令: 查询 key 的类型
TYPE key
修改
# 修改指定 key 的值
SET key value
# 将给定 key 的值设为 value,并返回 key 的旧值
GETSET key value
# 追加
APPEND key value
删除
# 通用命令: 删除 1 个或多个指定的 key
DEL key [key ...]
数字值
数字值在 Redis 中以字符串保存,但 Redis 也提供了一些将字符串解析为整数的操作:
# INCR(increment) 会将字符串值解析为整数,将其递增1,并将其设置为新值
INCR key
# INCRBY 可以指定递增的数值(整数)
INCRBY key increment
# DECR(decrement) 递减
DECR key
# 指定递减数值
DECRBY key decrement
示例:
127.0.0.1:6379> SET count 1
127.0.0.1:6379> GET count
# 存储的是字符串
"1"
127.0.0.1:6379> INCR count
# 输出新值
(integer) 2
127.0.0.1:6379> INCRBY count 4
(integer) 6
# Redis 无法将字符串解析为浮点数,对非整数字符串使用这些命令会报错
127.0.0.1:6379> INCRBY count 0.5
(error) ERR value is not an integer or out of range
127.0.0.1:6379> DECR count
(integer) 5
127.0.0.1:6379> DECRBY count 2
(integer) 3
数据类型 - 哈希/散列 Hashes
Hash 哈希(也叫散列)类型是一种字典结构,其存储了字段和字段值的映射(键值对),但字段值只能是字符串,不能是其他数据类型。也就是说,哈希类型不能嵌套其他数据类型。
注意:除了哈希类型,Redis 的其他数据类型同样不支持数据类型嵌套。
添加
# 添加或修改哈希表 key 中的键值对
# 如果不存在哈希 key 则创建
# 该命令只会增加 key 中的字段,或修改已有字段的值,不会覆写整个 key 的值
HSET key field value [field value ...]
# 同时将多个 field-value 对设置到哈希表 key 中(与 HSET 效果一样)
HMSET key field value [field value ...]
# 只有在字段 field 不存在时,才会设置哈希表字段的值
HSETNX key field value
示例:
127.0.0.1:6379> HSET myhash a 1 b 2
# 返回添加的字段的数量
(integer) 2
127.0.0.1:6379> HSET myhash a 11 c 3
# 只添加了一个 c 字段
(integer) 1
# 查看全部字段
127.0.0.1:6379> HKEYS myhash
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> HMSET myhash a 111 d 4
# 返回设置结果
OK
127.0.0.1:6379> HKEYS myhash
1) "a"
2) "b"
3) "c"
4) "d"
查询
# 获取所有哈希表 key 中的字段
HKEYS key
# 获取哈希表 key 中字段的数量
HLEN key
# 获取所有哈希表 key 中的字段值
HVALS key
# 获取单个字段的值
HGET key field
# 获取所有给定字段的值
HMGET key field [field ...]
# 获取所有哈希表 key 中的字段和值
HGETALL key
# 查看哈希表 key 中指定的字段是否存在
HEXISTS key field
示例:
127.0.0.1:6379> HSET myhash a 1 b 2 c 3
(integer) 3
127.0.0.1:6379> HKEYS myhash
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> HLEN myhash
(integer) 3
127.0.0.1:6379> HVALS myhash
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> HGET myhash a
"1"
127.0.0.1:6379> HMGET myhash a b
1) "1"
2) "2"
127.0.0.1:6379> HGETALL myhash
1) "a"
2) "1"
3) "b"
4) "2"
5) "c"
6) "3"
127.0.0.1:6379> HEXISTS myhash c
(integer) 1
修改
# 修改哈希表 key 中一个或多个字段的值
HSET key field value [field value ...]
# 为整数字符串值的字段提供的方法
# 注意:没有 HINCR HDECR HDECRBY 命令
HINCRBY key field increment
删除
# 删除一个或多个哈希表字段
HDEL key field [field ...]
# 通用命令: 删除整个哈希
DEL key [key ...]
数据类型 - 列表 Lists
列表类型的使用方式类似于编程语言中的数组,可以存储一个有序的字符串列表,常用的操作就是向列表两端添加元素,或者获得列表的某一个片段。
但是它和数组的概念还不太一样。
链表实现的 Redis 列表
要解释列表数据类型,最好从一点理论开始,因为信息技术人员经常以不正确的方式使用术语 “List”。例如,“Python Lists” 并不是名称所暗示的(链表),而是数组(相同的数据类型在 Ruby 中实际上被成为 Array)。
从一个非常普遍的观点来看,列表只是一系列有序元素:10, 20, 1, 2, 3
是一个列表。但是,使用数组实现的列表的属性与使用链表实现的列表的属性非常不同。
Redis 列表是通过双向链表实现的,所有向列表两端添加或获取元素的时间复杂度为O(1),获取越接近两端的元素速度就越快。
这意味着,在列表的开头或结尾添加/获取元素的操作都会在固定时间内完成。例如向包含 10 个元素的列表头添加新元素的速度和向包含 1000 万个元素的列表头添加元素的速度相同。
缺点:使用链表的代价是通过索引访问元素比较慢。
在用数组实现的列表中,按索引访问元素的速度非常快,而在用链表实现的列表中,按索引访问元素的速度则不快,它会从开头第一个元素开始一个一个查找。在链表中,需要与所访问元素的索引成比例的工作量。
优点:对于数据库系统来说,能够以非常快的方式将元素添加到非常长的列表中是至关重要的。另一个强大的优势是 Redis 列表可以在固定的时间内以固定的长度获取元素。
这种特性使列表类型能非常快速地完成关系数据库难以应付的场景:例如社交网站的新鲜事,我们关心的只是最新内容,使用列表类型存储,即使新鲜事的总数达到几千万个,获取其中最新的 100 条数据也是极快的。同样因为在两端插入记录的时间复杂度是 O(1),列表类型也适合用来记录日志,可以保证加入新日志的速度不会受到已有日志数量额影响。
当需要快速访问大量元素集合的中间部分时,可以使用另一种数据结构(Sorted sets)。
添加
# 将一个或多个元素插入到列表头部(或左侧)(left push)
# 如果 key 不存在,则创建
# 多个元素是依次插入的,即最后添加的元素最终作为列表的第一个元素
LPUSH key element [element ...]
# 在列表中查找到的第一个参考元素(pivot)前或后插入元素
# 当 key 不存在,则视为空列表,不执行任何操作
# 当 key 存在,但存储的不是列表类型的值时,返回错误
LINSERT key BEFORE|AFTER pivot element
# 如果列表 key 存在,则将一个元素插入到列表头部
LPUSHX key element
# 将一个或多个元素插入到列表尾部(或右侧)(right push)
RPUSH key element [element ...]
# 如果列表 key 存在,则将一个元素插入到列表尾部
RPUSHX key element
示例:
127.0.0.1:6379> LPUSH mylist 1 2 2 3
# 返回列表元素的数量
(integer) 4
# 查询指定索引范围内的元素 `start:0, stop:-1` 表示查询全部
127.0.0.1:6379> LRANGE mylist 0 -1
# 向头部依次插入多个元素,顺序与插入顺序是相反的
1) "3"
2) "2"
3) "2"
4) "1"
127.0.0.1:6379> LINSERT mylist BEFORE 2 a
# 返回列表元素的数量
(integer) 5
127.0.0.1:6379> LRANGE mylist 0 -1
# 只在第一个查询到的参考元素前插入一次
1) "3"
2) "a"
3) "2"
4) "2"
5) "1"
127.0.0.1:6379> LPUSHX mylist2 x
# 不存在的 key 不执行插入
(integer) 0
127.0.0.1:6379> LRANGE mylist2 0 -1
(empty array)
127.0.0.1:6379> RPUSH mylist 7 8 9
(integer) 8
127.0.0.1:6379> LRANGE mylist 0 -1
1) "3"
2) "a"
3) "2"
4) "2"
5) "1"
6) "7"
7) "8"
8) "9"
查询
# 通过索引获取列表中的元素
LINDEX key index
# 获取列表长度
LLEN key
# 获取列表指定索引范围内的元素
# stop 所在的元素也会被返回
# 正数表示从前往后,负数表示从后往前,例如 stop 为 -1 表示查询到底
LRANGE key start stop
修改
# 通过索引设置列表元素的值
# 索引超出列表范围会报错
LSET key index value
删除
# 从头部(左侧)删除并获取列表的元素,默认删除一个
# count 指定删除的元素个数,默认为最小值 1
LPOP key [count]
# 从尾部(右侧)删除并获取列表的元素,默认删除一个
RPOP key [count]
# 删除指定数量的等于指定值的列表元素
# count>0: 从头到尾删除 count 个数的等于 element 的元素
# count<0: 从尾到头删除 count 个数的等于 element 的元素
# count=0: 删除等于 element 的所有元素
LREM key count element
# 修剪列表,使列表只保留指定索引范围的元素,删除范围外的元素
LTRIM key start stop
# 删除并获取 source 列表的最后一个元素,将该元素添加到 destination 列表的头部,并返回该元素
RPOPLPUSH source destination
# 其他阻塞版本的命令 -------------------------------
# LPOP 的阻塞版本
# 按顺序检查给定的列表,如果其中至少有一个列表不是空列表,则 pop 它的第一个元素并返回
# 当给定的一个或多个列表中没有要 pop 的元素(空列表)时,会阻塞连接,直到另一个客户端对其中一个列表执行 LPUSH 或 RPUSH 添加元素操作。
# timeout 指定阻塞的最大秒数,如果设置为 0,则表示无限期阻塞
# 当 BLPOP 导致客户端阻塞并指定了非 0 的 timeout 时,客户端会等待两种情况:
# 1. 到达指定的超时时间,取消阻塞
# 2. 在超时时间内,对至少一个列表执行 PUSH 操作,客户端会执行 POP 操作并取消阻塞
# 如果
BLPOP key [key ...] timeout
# RPOP 的阻塞版本
BRPOP key [key ...] timeout
# RPOPLPUSH 的阻塞版本
# 当 source 列表为空时阻塞连接
BPOPLPUSH source destination timeout
数据类型 - 集合 Sets
集合类型和数学中的集合概念相似,集合中的元素是唯一的、无序的,简单理解集合就是没有顺序且不重复的字符串列表。
集合类型和列表类型有相似之处,它们的主要区别是:
- 列表是有序的,集合是无序的(Sorted sets 是有序的)
- 列表数据可以重复,集合中没有重复数据
集合类型的常用操作是向集合中加入或删除元素、判断某个元素是否存在等。由于集合类型在 Redis 内部是使用值为空的散列表实现的,所以这些操作的时间复杂度都是O(1)。
最方便的是多个集合之间还可以进行并集、交集和差集聚合运算。
添加
# 向集合添加一个或多个成员
# 如果 key 不存在,则创建;如果 key 存储的是不是集合类型则报错
# 如果 member 存在,则忽略
SADD key member [member ...]
示例:
127.0.0.1:6379> SADD myset 1 2 3 a b c
(integer) 6
# 查看集合下的元素
127.0.0.1:6379> SMEMBERS myset
# 集合是无序的,添加结果与插入时的顺序可能会不一样
1) "2"
2) "a"
3) "3"
4) "c"
5) "1"
6) "b"
查询
# 返回集合中的所有成员
# 效果等同于 SINTER key
SMEMBERS key
# 获取集合的基数(cardinality),即成员数
SCARD key
# 判断 member 元素是否是集合 key 的成员
SISMEMBER key member
# 随机返回集合中一个(默认)或多个成员
# count>0: 返回包含不同元素的数组,数组长度取 count 和 基数(SCARD) 较低的值
# count<0: 返回允许包含相同元素的数组,数组长度为 count 的绝对值
# count=0: 返回空数组
SRANDMEMBER key [count]
删除
# 移除集合中一个或多个成员
SREM key member [member ...]
# 随机移除并返回集合中的一个或多个成员
SPOP key [count]
# 将 member 从 source 集合移动到 destination 集合
SMOVE source destination member
集合间聚合运算
多个集合之间还可以进行并集、交集和差集聚合运算。
# 返回由第一个集合和其他集合之间的差异产生的集合
SDIFF key [key ...]
# 返回由所有给定集合的交集生成的集合
# 只指定第一个 key(SINTER KEY),等同于 SMEMBERS key
SINTER key [key ...]
# 返回由所有给定集合的并集产生的集合
SUNION key [key ...]
# 返回给定所有集合的差集并存储在 destination 中
SDIFFSTORE destination key [key ...]
# 返回给定所有集合的交集并存储在 destination 中
SINTERSTORE destination key [key ...]
# 所有给定集合的并集存储在 destination 集合中
SUNIONSTORE destination key [key ...]
使用场景
- 跟踪一些唯一性数据
- 比如访问网站的唯一 IP 地址信息,每次访问网站的时候记录用户 IP 地址,SET 自动保证数据的唯一不重复
- 充分利用 SET 聚合操作方便高效的特性,用于维护数据对象之间的关联关系
- 比如所有购买A商品的客户 ID 存储到指定的 SET 中,所有购买B商品的客户 ID 存储到指定的 SET 中,如果我们想要获取有哪个客户同时购买了这两个商品,我们只需要使用交集操作就可以轻松的查出来
数据类型 - 有序集合 Sorted sets
有序集合是一种类似于 Set 和 Hash 之间的混合数据类型。
- 与集合一样,有序集合由唯一的、不重复的字符串元素组成
- 集合中的元素没有排序,但有序集合中的每个元素都会关联一个 double 类型的 score(称为分数)(这就是为什么该类型也类似于哈希,因为每个元素都映射到一个值)
- 有序集合中的元素是根据以下规则进行排序的:
- 如果 A 和 B 分数不同,分数低的在前
- 如果 A 和 B 分数相同,则按照字典序排序,例如 a 在 b 前面
vs Lists 类型
有序集合在某些方面和列表类型有些相似:
- 相同点:
- 两者都是有序的
- 两者都可以获得某一范围的元素
- 不同点:
- 列表类型通过链表实现,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会较慢,所以它更适合实现如“新鲜事”或“日志”这样很少访问中间元素的应用
- 有序集合使用包含一个哈希表的数据结构实现,所以即使读取位于中间部分的数据,速度也很快
- 列表不能简单的调整某个元素的位置,但是有序集合可以(插入元素或更改元素的分数的时候就已经排好序了)
- 有序集合要比列表更耗费内存
应用场景
有序集合的典型应用场景:
(1)排行榜
例如一个大型在线游戏的积分排行榜,每当玩家的分数发生变化时,可以执行 ZADD
命令更新玩家的分数,此后再通过 ZRANGE
命令获取积分 TOPTEN 的用户信息。当然我们也可以利用 ZRANK
命令通过 username 来获取玩家的排行信息。最后我们将组合使用 ZRANGE
和 ZRANK
命令快速的获取和某个玩家积分相近的其他用户的信息。
(2)微博热搜
假设我们现在要获取热门的帖子或搜索,比如我们常用的微博热搜。
首先,我们需要一个衡量的标准,定量的量度热搜的热门程度。假设我们有一个字段叫回复量,回复量越高就越热门。
如果我们用关系型数据库来获取的话,用 SQL 语句实现很简单:
SELECT * FROM message ORDER BY backsum LIMIT 10
但是当数据量很大的时候,效率很低,同时如果建立索引又要消耗大量的资源,同时增加负载。
使用 Redis 的时候,我们不需要存储多余的信息,只需要存储帖子 id 和回复量两个信息就可以了。
添加
# 创建有序集合、向有序集合添加一个或多个成员、更新已存在成员的分数
# `score` 是双精度浮点数, `+inf`、`-inf` 也是有效值(表示负无穷大和正无穷大)
ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
选项
ZADD 支持一个选项列表,在 key 之后和第一个 score 之前指定,选项包括:
XX
:仅更新已存在的元素,不要添加新元素NX
:仅添加新元素,不要更新已存在的元素LT
:仅当新分数小于当前分数时更新现有元素,此标志不阻止添加新元素GT
:仅当新分数大于当前分数时更新现有元素,此标志不阻止添加新元素CH
:ZADD 默认会返回新添加的元素数。使用CH
选项,将改为返回更改的元素数(CH 是 changed 的缩写)。更改的元素指添加的新元素和更新分数的已存在元素,所以在命令行中指定的与过去具有相同分数的元素不被计算在内。INCR
:(increment)指定此选项,ZADD 的行为类似 ZINCRBY,会将分数增量添加到元素的当前分数上,在此模式中只能指定一个 score-member 对。指定此选项,ZADD 的返回值为元素最新的分数。
注意:GT
,LT
和 NX
选项是互斥的。
排序
有序集合按分数升序排序,同一元素只存在一次,不允许重复元素。可通过 ZSCORE 命令检索元素的当前分数,也可用于验证元素是否存在。
当多个元素具有相同的分数,则按照字典序排序。
查询
区间查询
# 执行不同类型的范围查询,返回有序集合指定区间内的成员
ZRANGE key min max [BYSCORE|BYLEX] [REV] [LIMIT offset count] [WITHSCORES]
选项:
- 查询类型:
- 默认:指定排名(rank)Index 索引区间,
min
和max
表示从 0 开始的索引,如果为负数,表示从末尾开始的偏移量,例如-1
是有序集合的最后一个元素,-2
是倒数第二个。 BYSCORE
:指定分数(Score)区间- 返回有序集合中分数等于或介于
min
和max
之间的元素范围 - 分数可以指定
-inf
和+inf
- 默认情况下,
min
和max
指定的是闭区间[min, max]
,即指定的范围包含等于min
或max
,可以通过在分数前面加上字符(
将其范围闭区间,即范围不包括等于min
或max
,例如(1 5
表示(1, 5]
,(1 (5
表示(1, 5)
。 - 使用该选项类似 ZRANGEBYSCORE 命令。
- 返回有序集合中分数等于或介于
BYLEX
:指定字典(Lexicographical)区间min
和max
必须是以(
或[
开头的字符串,以分别指定范围是开区间还是闭区间。min
和max
也可以是-
和+
特殊值,分别表示负无穷大和正无穷大。- 注意:字典排序依赖于具有相同分数的所有元素,当元素具有不同分数时,排序会优先以分数排序。
- 使用该选项类似 ZRANGEBYLEX 命令。
- 默认:指定排名(rank)Index 索引区间,
REV
选项指定是否倒序排序并返回- 此选项仅支持默认索引查询类型
LIMIT offset count
用于从匹配元素中获取子返回,类似 SQL 中的SELECT LIMIT offset, count
。- 从匹配结果的
offset
索引位置开始(第一个为 0),返回count
数量的匹配元素。 - 如果
count
为负数,则返回从offset
到结尾的所有元素。 - 使用此选项
offset
和count
都必填。 - 此选项仅支持
BYSCORE
和BYLEX
查询类型
- 从匹配结果的
WITHSCORES
:将分数也一并返回,返回的列表包含member1 score1 member2 score2 ...
- 此选项仅支持
BYSCORE
和默认索引查询类型
- 此选项仅支持
示例:
127.0.0.1:6379> ZADD myzsort 1 a 2 b 2 c 1 d 3 e
(integer) 5
# 排名索引区间+反向排序
127.0.0.1:6379> ZRANGE myzsort 1 3 REV
1) "c"
2) "b"
3) "d"
# 分数区间
127.0.0.1:6379> ZRANGE myzsort 1 2 BYSCORE
1) "a"
2) "d"
3) "b"
4) "c"
# 指定子范围
127.0.0.1:6379> ZRANGE myzsort 1 2 BYSCORE LIMIT 1 2
1) "d"
2) "b"
# 返回分数
127.0.0.1:6379> ZRANGE myzsort 1 2 BYSCORE LIMIT 1 2 WITHSCORES
1) "d"
2) "1"
3) "b"
4) "2"
# 字典区间,优先分数排序
127.0.0.1:6379> ZRANGE myzsort (a [e BYLEX
1) "d"
2) "b"
3) "c"
4) "e"
该方法可以替换以下命令:ZREVRANG、ZRANGEBYSCORE、ZREVRANGEBYSCORE、ZRANGEBYLEX 和 ZREVRANGEBYLEX
# 通过索引区间返回有序集合指定区间内的元素,分数从高到低排序
ZREVRANGE key start stop [WITHSCORES]
# 返回有序集中指定分数区间内的元素,分数从低到高排序
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
# 返回有序集中指定分数区间内的元素,分数从高到低排序
ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
# 返回有序集中指定字典区间的元素,分数从低到高,同分元素按字典序从低到高排序
ZRANGEBYLEX key min max [LIMIT offset count]
# 返回有序集中指定字典区间的元素,分数从高到低,同分元素按字典序从高到低排序
ZREMRANGEBYLEX key min max
其他查询
下次从这里看
# 返回有序集合中指定成员的排名,有序集成员按分数值(从低到高)排序,排名(或索引)从 0 开始
ZRANK key member
# 获取分数从高度到底排列的成员排名
ZREVRANK key member
# 获取有序集合的成员数
ZCARD key
# 返回有序集中,成员的分数值
ZSCORE key member
# 计算在有序集合中指定区间分数的成员数
# 默认是闭区间,可以在分数前加 `(` 指定开区间,也可指定 `-inf` 和 `+inf`
ZCOUNT key min max
修改
# 向有序集合添加一个或多个成员,或者更新已存在成员的分数
ZADD key [XX] [GT|LT] [CH] [INCR] score member [score member ...]
# 有序集合中对指定成员的分数加上增量 increment
ZINCRBY key increment member
删除
# 移除有序集合中的一个或多个成员
ZREM key member [member ...]
# 移除有序集合中给定的排名区间的所有成员
ZREMRANGEBYRANK key start stop
# 移除有序集合中给定的分数区间的所有成员
ZREMRANGEBYSCORE key min max
# 移除有序集合中给定的字典序区间的所有成员
ZREMRANGEBYLEX key min max
有序集合间聚合运算
# 计算给定的一个或多个有序集的交集,并将结果集存储在新的有序集合 destination 中
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
# 计算给定的一个或多个有序集的并集,并将结果集存储在新的有序集合 destination 中
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
- destination:存储结果的目标 key,如果目标已存在,则会覆盖
- numkeys:在指定计算的 keys 之前,必须提供 key 的数量
- 如果 numkeys 与指定的 keys 的数量不一致,则报语法错误。
- WEIGHTS:权重,为每个有序集合指定乘法因子,意味着在传递给聚合函数之前,每个集合中的每个元素的分数都将乘以该因子。默认情况下,权重为 1。
- 如果使用该参数,则必须为每个集合指定乘法因子,如果指定的因子数量与 keys 数量不一致,则报语法错误.
- AGGREGATE:聚合选项,指定在聚合时如何计算联合元素的分数。
- SUM:默认值,相同元素取分数的求和
- MIN:相同元素取分数的最小分数
- MAX:相同元素取分数的最大分数
通用命令
# 返回与模式匹配的所有的 key
KEYS pattern
# 返回所有 key
KEYS *
# 返回所有以 my 开头的 key
KEYS my*
# 获取 key 的类型
TYPE key
# 查询某个 key 是否存在,返回存在的数量
EXISTS key [key ...]
# 将 key 改名为 newkey
RENAME key newkey
# 删除指定 key
DEL key [key ...]
# 从当前数据库中随机返回(不删除)一个 key
RANDOMKEY
# 清空当前数据库所有内容
FLUSHDB [ASYNC|SYNC]
# 清空所有数据库内容
FLUSHALL [ASYNC|SYNC]
# 将当前数据库的 key 移动到给定的数据库 db 当中
# 如果目标数据库中存在 key,或当前数据库中没有 key,则不执行任何操作
# 如果移动成功返回 1,移动失败返回 0
MOVE key db
Redis 过期时间
在实际开发中经常会遇到一些有时效的数据,比如限时优惠活动、缓存或验证码等,过了一定时间就需要删除这些数据。在关系数据库中一般需要额外的一个字段记录到期时间,然后定期检测删除过期数据。而在 Redis 中可以设置一个键的过期时间,到时间后 Redis 会自动删除它。
设置键的过期时间
# 为给定的 key 设置生存时间(秒)
EXPIRE key seconds [NX|XX|GT|LT]
# 为给定的 key 设置时间(毫秒)
PEXPIRE key milliseconds [NX|XX|GT|LT]
# 为给定的 key 设置生存时间(UNIX 时间戳,以秒为单位)
EXPIREAT key timestamp [NX|XX|GT|LT]
# 为给定的 key 设置生存时间(UNIX 时间戳,以毫秒为单位)
PEXPIREAT key milliseconds-timestamp [NX|XX|GT|LT]
选项:
- NX:仅当 key 没有到期时间才设置
- XX:仅当 key 当前具有到期时间才设置
- GT:仅当新的到期时间大于当前到期时间才设置
- LT:仅当新的到期时间小于当前到期时间才设置
持久 key (未设置到期时间)的当前到期时间被视为无限的 TTL。GT、LT 和 NX 是互斥的。
上面四个命令为给定的 key 设置生存时间,当 key 过期时,它将会被自动删除。
为 key 设置的过期时间,也是以键值结构存储在一个字典里,键是一个指向这个 key 的指针,值是一个长整型的 UNIX 时间戳。
注意:使用非正数调用 EXPIRE/PEXPIRE 或使用过去的时间调用 EXPIREAT/PEXPIREAT 将导致 key 被删除,而不是过期(因此,触发的事件将是 del
,而不是 expired
)。
获取键的过期时间
# 以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
TTL key
# 类似于 TTL,单位为毫秒
PTTL key
# 以秒为单位,返回给定 key 的到期时间戳
EXPIRETIME key
# 类似 EXPIRETIME,单位为毫秒
PEXPIRETIME key
获取过期时间的命令如果返回负数,则表示错误:
-1
:key 存在,但没有过期时间-2
:key 不存在
清除键的过期时间
在 Redis 术语中,设置了过期时间的 key 被称为 volatile (易失的),没有关联过期时间的 key 被称为 persistent (持久的)。
清除过期时间的方式有两种:
1、使用 PERSIST 命令清除 key 的过期时间,将 key 从 易失的 转化为 持久的。
PERSIST key
2、删除或覆盖 key 内容的命令
包括 DEL、SET、GETSET 和所有 *STORE 命令都会清除过期时间。
而所有在概念上改变存储在 key 上的值,而不是使用新值替换它的操作,将保持过期时间不变。例如 INCR 递增 key 的值、使用 LPUSH 将新值推送到列表中,或使用 HSET 更改哈希的字段值,这些操作都将保持过期时间不变。
如果使用 RENAME 重命名一个 key,则关联的过期时间将传输到新的 key 名。
如果 Key-A 重命名到一个已存在的 Key-B,则属于覆盖内容的操作。不论这个 Key-B 是否有过期时间,它都将继承 Key-A 的过期时间。