1. 全局命令 - 键(Key)的通用操作
Redis 对键(Key)的操作是通用的,不管 value 是五种类型中的哪一种类型,都可以用的操作
1.1. KEYS 查询键
1.1.1. 基础使用
| |
获取所有与pattern匹配的key,*表示任意0个或多个字符,?表示任意一个字符。
比如:
KEYS *匹配数据库中所有keyKEYS h?llo匹配hello,hallo和hxllo等KEYS h*llo匹配hllo和heeeeello等KEYS h[ae]llo匹配hello和hallo,但不匹配hillo
示例:
| |
1.1.2. keys 命令存在的问题
因为 Redis 是单线程的。keys 指令会导致线程阻塞一段时间,直到执行完毕,服务才能恢复。所以值得注意的是,如果存在大量键,线上禁止使用此指令
1.2. SCAN 迭代集合元素
1.2.1. 基础使用
| |
SCAN 命令及其相关的命令(SSCAN、HSCAN、ZSCAN)都用于增量地迭代(incrementally iterate)一集元素(a collection of elements):
SCAN命令用于迭代当前数据库中的数据库键。SSCAN命令用于迭代集合键中的元素。HSCAN命令用于迭代哈希键中的键值对。ZSCAN命令用于迭代有序集合中的元素(包括元素成员和元素分值)。
以上列出的四个命令都支持增量式迭代,它们每次执行都只会返回少量元素,所以这些命令可以用于生产环境,而不会出现像在大量键的情况下 KEYS 命令造成阻塞的问题。
1.2.2. SCAN 命令优缺点
scan 的优点是:该命令采用渐进式遍历的方式来解决 keys 命令可能带来的阻塞问题,每次 scan 命令的时间复杂度是 O(1),但是要真正实现 keys 的功能,需要执行多次 scan。
scan 的缺点是:在执行命令的过程中,如果有键的变化(增加、删除、修改),遍历过程可能会出现,新增的键可能没有遍历到、遍历出了重复的键等情况。即 scan 命令并不能保证完整的遍历出来所有的键。
1.3. DBSIZE 查询键总数
| |
查询目前存在的键的总数量。
示例:
| |
1.4. EXISTS 检查键是否存在
| |
判断该key是否存在,返回1表示存在,0表示不存在
| |
1.5. DEL 删除键
| |
删除给定的一个或多个 key。并返回被删除 key 的数量,如果删除不存在键返回0。无论值是什么数据结构类型,del命令都可以将其删除
| |
1.6. EXPIRE 设置过期时间(秒级别)
| |
为给定 key 设置生存时间(单位:秒),当 key 过期时(生存时间为 0 ),它会被自动删除这个key。
| |
1.7. TTL 查询剩余生存时间(秒级别)
| |
获取该key所剩余的超时时间(TTL, time to live),返回值类型如下:
- 当
key不存在时,返回-2 - 当
key存在但没有设置剩余生存时间时,返回-1 - 当
key存在且有设置剩余时间,则以秒为单位,返回大于等于0的整数(即key的剩余生存时间)
注:在 Redis 2.8 以前,当
key不存在,或者key没有设置剩余生存时间时,命令都返回-1
| |
1.8. EXPIREAT 设置生存时间(秒级别时间戳)
| |
EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置生存时间。不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。
如果生存时间设置成功,返回1;当key不存在或没办法设置生存时间,返回0。
| |
1.9. PEXPIRE 设置生存时间(毫秒级别)
| |
这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而EXPIRE命令以秒为单位。设置成功,返回1;key不存在或设置失败,返回0
| |
1.10. PEXPIREAT 设置生存时间(毫秒级别时间戳)
| |
这个命令和 expireat 命令类似,但它以毫秒为单位设置 key 的过期 unix 时间戳,而 expireat 命令则以秒为单位。如果生存时间设置成功,返回1。 当 key 不存在或没办法设置生存时间时,返回0
| |
1.11. PTTL 查询剩余生存时间(毫秒级别)
| |
这个命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间,而 TTL 命令则以秒为单位。返回值类型如下:
- 当
key不存在时,返回-2 - 当
key存在但没有设置剩余生存时间时,返回-1 - 当
key存在且有设置剩余时间,则以毫秒为单位,返回大于等于0的整数(即key的剩余生存时间)
注:在 Redis 2.8 以前,当
key不存在,或者key没有设置剩余生存时间时,命令都返回-1
1.12. PERSIST 移除生存时间
| |
移除给定 key 的生存时间,相当于将这个key从“易失的”(带生存时间的key)转换成“持久的”(一个不带生存时间、永不过期的key)。当生存时间移除成功时,返回1; 如果 key 不存在或 key 没有设置生存时间,返回0。
| |
1.13. TYPE 键存储的数据结构类型
| |
返回 key 所储存的值的数据结构类型(以字符串形式返回)。返回值:
none(key不存在)string(字符串)list(列表)set(集合)zset(有序集)hash(哈希表)stream(流)
| |
1.14. RANDOMKEY 随机获取一个key
| |
从当前数据库中随机返回(不删除)一个key。当数据库不为空时,返回一个key。当数据库为空时,返回nil
| |
1.15. RENAME 重命名
| |
将 key 重命名为 newkey。返回值如下:
- 当
key重命名成功时提示OK - 当
key和newkey相同,或者key不存在时,返回一个错误
特别注意:
- 当
newkey已经存在时,RENAME命令会覆盖旧值。为了防止被强行rename,Redis提供了renamenx命令,确保只有newKey不存在时候才被覆盖。- 通过测试可知,由于重命名键期间会执行
del命令删除旧的键,如果键对应的值比较大,会存在阻塞Redis的可能性
| |
1.16. SELECT 切换数据库
| |
切换到指定的数据库,数据库索引号 index 用数字值指定。
一个 Redis 服务器可以包括多个数据库,客户端可以指连接 Redis 中的的哪个数据库,就好比一个mysql服务器中创建多个数据库,客户端连接时指定连接到哪个数据库。Redis 实例最多可提供 16 个数据库,索引值从0到15,客户端默认连接索引值为0的数据库,也可以通过select命令选择哪个数据库。如果选择 16 时会报错,说明没有编号为 16 的数据库。
| |
1.17. MOVE 迁移键
| |
将当前数据库的 key 移动到给定的数据库 db 当中。移动成功返回1,失败则返回0
如果当前数据库(源数据库)和给定数据库(目标数据库)有相同名字的给定 key ,或者 key 不存在于当前数据库,那么 MOVE 命令没有任何效果。因此,也可以利用这一特性,将 MOVE 命令当作锁(locking)原语(primitive)。
| |
1.18. 其他小结
1.18.1. KEYS 与 DBSIZE 命令小结
dbsize命令在计算键总数时不会遍历所有键,而是直接获取 Redis 内置的键总数变量,所以dbsize命令的时间复杂度是O(1)。keys命令会遍历所有键,所以它的时间复杂度是o(n),当 Redis 保存了大量键时线上环境禁止使用keys命令。
1.18.2. 关于使用 Redis 相关过期命令时注意点
- 如果使用
expire key命令时相应的键不存在,返回结果为 0 - 如果过期时间为负值,键会立即被删除,效果与使用
del命令一样 persist命令可以将键的过期时间清除- 对于字符串类型的键,执行
set命令后,会重置过期时间(如果没有设置则重置为不过期),这个问题很容易在开发中被忽视。 - Redis 不支持二级数据结构(例如哈希、列表)内部元素的过期功能,例如不能对列表类型的一个元素做过期时间设置。
- 如果关了 Redis 服务器端,在默认情况下从控制台插入的
key=value键值对数据,就算 key 时间未到,也会自动销毁。
2. String 类型命令(重点)
字符串类型是 Redis 中最为基础的数据存储类型,它在 Redis 中是二进制安全的,这便意味着该类型存入和获取的数据相同。字符串类型的值实际可以是简单的字符串、复杂的字符串(例如 JSON、XML)、数字(整数、浮点数),甚至是二进制(图片、音频、视频),在 Redis 中字符串类型的 Value 最多可以容纳的数据长度是 512M。
注:Redis 所有类型的键都是字符串类型,而且其他几种数据结构都是在字符串类型基础上构建的。
2.1. SET 赋值
| |
设定key持有指定的字符串value,如果该key存在则进行覆盖操作,无视类型。返回结果为OK代表设置成功。
当 SET 命令对一个带有生存时间(TTL)的键进行设置之后,该键原有的生存时间将被清除。
可选参数:
从 Redis 2.6.12 版本开始,SET命令的行为可以通过一系列参数来修改:
EX seconds:将键的过期时间设置为seconds秒。执行SET key value EX seconds的效果等同于执行SETEX key seconds valuePX milliseconds:将键的过期时间设置为milliseconds毫秒。执行SET key value PX milliseconds的效果等同于执行PSETEX key milliseconds valueNX:只在键不存在时,才对键进行设置操作。执行SET key value NX的效果等同于执行SETNX key valueXX:只在键已经存在时,才对键进行设置操作
note:因为
SET命令可以通过参数来实现SETNX、SETEX以及PSETEX命令的效果,所以 Redis 将来的版本可能会移除并废弃SETNX、SETEX和PSETEX这三个命令。
返回值:
- 在 Redis 2.6.12 版本以前,
SET命令总是返回OK - 从 Redis 2.6.12 版本开始,
SET命令只在设置操作成功完成时才返回OK;如果命令使用了NX或者XX选项,但是因为条件没达到而造成设置操作未执行,那么命令将返回空批量回复(NULL Bulk Reply)
代码示例:
| |
2.2. SETNX 不存在时赋值
| |
只在键key不存在的情况下,将键key的值设置为value。若键key已经存在,则SETNX命令不做任何动作。设置成功时返回1,设置失败时返回0
SETNX是『SET if Not exists』(如果不存在,则SET)的简写。
| |
note: 由于Redis的单线程命令处理机制,如果有多个客户端同时执行
setnx key value,根据setnx的特性只有一个客户端能设置成功,setnx可以作为分布式锁的一种实现方案。
2.3. SETEX 赋值并设置生存时间(秒级别)
| |
将键 key 的值设置为 value,并将键 key 的生存时间设置为 seconds 秒钟。如果键 key 已经存在, 那么 SETEX 命令将覆盖已有的值。设置成功时返回OK。 当 seconds 参数不合法时,命令将返回一个错误。
SETEX 命令效果相当于以下命令:
| |
SETEX 与以上两条命令组合的区别在于 SETEX 是一个原子(atomic)操作,它可以在同一时间内完成设置值和设置过期时间这两个操作,因此 SETEX 命令在储存缓存的时候非常实用。
代码示例:
| |
2.4. PSETEX 赋值并设置生存时间(毫秒级别)
| |
PSETEX 和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而 SETEX 命令则以秒为单位进行设置。在设置成功时返回OK
代码示例:
| |
2.5. GET 取值
| |
返回与键 key 相关联的字符串值。返回值情况如下:
- 如果键
key不存在, 那么返回特殊值nil;否则,返回键key的值 - 如果键
key的值并非字符串类型,那么返回一个错误,因为GET命令只能用于字符串值。
代码示例:
| |
2.6. GETSET 先取值再赋值
| |
将键 key 的值设为 value,并返回键 key 在被设置之前的旧值。返回值情况如下:
- 返回给定键
key的旧值 - 如果键
key没有旧值,也即是说,键key在被设置之前并不存在,那么命令返回nil - 如果键
key存在但不是字符串类型时,命令返回一个错误
代码示例:
| |
2.7. MSET 批量赋值
| |
同时为多个键批量设置值。MSET 命令总是返回OK。如果某个给定键已经存在,那么 MSET 将使用新值去覆盖旧值。如果不想覆盖旧值,则使用MSETNX,此命令只会在所有给定键都不存在的情况下进行设置。
MSET 是一个原子性(atomic)操作,所有给定键都会在同一时间内被设置,不会出现某些键被设置了但是另一些键没有被设置的情况。
代码示例:
| |
2.8. MGET 批量取值
| |
返回给定的一个或多个字符串键的值。MGET 命令结果是返回一个列表,列表中包含了所有给定键的值,是按照传入键的顺序返回。如果给定的字符串键里面,有某个键不存在,那么这个键的值将以特殊值 nil 表示。
代码示例:
| |
note:
批量操作命令可以有效提高效率,假如没有
mget这样的命令,要执行n次get命令具体耗时是:n次get时间=n次网络时间+n次命令时间使用
mget命令后,要执行n次get命令操作具体耗时是:n次get时间=1次网络时间+n次命令时间Redis可以支撑每秒数万的读写操作,但是这指的是Redis服务端的处理能力,对于客户端来说,一次命令除了命令时间还是有网络时间,假设网络时间为1毫秒,命令时间为0.1毫秒(按照每秒处理1万条命令算),那么执行1000次
get命令需要1.1秒(1000*1+1000*0.1=1100ms),1次mget命令的需要0.101秒(1*1+1000*0.1=101ms)。
2.9. INCR 数字递增
| |
为键 key 储存的数字值加1。INCR 命令会返回键 key 在执行加1操作之后的值。存在以下3种情况:
- 如果键
key不存在,那么它的值会先被初始化为0,然后再执行INCR命令。 - 如果键
key存在并且储存的值为数字,则在原数值加1后替换原来的值,并返回加1后的结果 - 如果键
key储存的值不能被解释为数字,那么INCR命令将返回一个错误。
note:
- 本操作的值限制在 64 位(bit)有符号数字表示之内。
INCR命令是一个针对字符串的操作。因为 Redis 并没有专用的整数类型,所以键key储存的值在执行INCR命令时会被解释为十进制64位有符号整数。
代码示例:
| |
2.10. DECR 数字递减
| |
为键 key 储存的数字值减1。DECR 命令会返回键 key 在执行减1操作之后的值。存在以下3种情况:
- 如果键
key不存在,那么它的值会先被初始化为0,然后再执行DECR命令。 - 如果键
key存在并且储存的值为数字,则在原数值减1后替换原来的值,并返回减1后的结果 - 如果键
key储存的值不能被解释为数字,那么DECR命令将返回一个错误。
note: 本操作的值限制在 64 位(bit)有符号数字表示之内。
| |
2.11. INCRBY/DECRBY 数字递增/递减指定指定值
| |
为键 key 储存的数字值加上增量 increment/减去减量decrement,并返回该值。存在以下3种情况:
- 如果键
key不存在,那么它的值会先被初始化为0,然后再执行INCRBY/DECRBY命令。 - 如果键
key存在并且储存的值为数字,则在原数值加上increment值/减去decrement值后替换原来的值,并返回结果 - 如果键
key储存的值不能被解释为数字,那么INCRBY/DECRBY命令将返回一个错误。
note: 本操作的值限制在 64 位(bit)有符号数字表示之内。
| |
2.12. APPEND 字符追加
| |
append 指令可以向字符串尾部追加值。返回值为追加 value 之后,键 key 的值的长度。
- 如果键
key已经存在并且它的值是一个字符串,APPEND命令将把value追加到键key现有值的末尾。 - 如果键
key不存在,APPEND就简单地将键key的值设为value,就像执行SET key value一样。
| |
2.13. STRLEN 字符串长度
| |
返回键 key 储存的字符串值的长度。当键 key 不存在时,命令返回0。当 key 储存的不是字符串值时,返回一个错误。
| |
注意:每个中文占 3 个字节
2.14. GETSET 设置并返回原值
| |
getset 和 set 一样会设置值,将键 key 的值设为 value,但 GETSET 命令会返回键 key 在被设置之前的旧值。存在以下特殊情况:
- 当键
key在被设置之前并不存在,返回nil - 当键
key存在但不是字符串类型时,返回一个错误
| |
2.15. SETRANGE 设置指定位置的字符
| |
从偏移量 offset 开始, 用 value 参数覆写(overwrite)键 key 储存的字符串值,并返回被修改之后,字符串值的长度。不存在的键 key 当作空白字符串处理。值的下标是从0开始计算。
SETRANGE 命令会确保字符串足够长以便将 value 设置到指定的偏移量上, 如果键 key 原来储存的字符串长度比偏移量小(比如字符串只有5个字符长,但设置的offset是10),那么原字符和偏移量之间的空白将用零字节(zerobytes, "\x00")进行填充。
Warning: 当生成一个很长的字符串时, Redis 需要分配内存空间, 该操作有时候可能会造成服务器阻塞(block)。
| |
2.16. GETRANGE 截取字符串
| |
返回键 key 储存的字符串值的指定部分,字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。负数偏移量表示从字符串的末尾开始计数,-1 表示最后一个字符,-2 表示倒数第二个字符,以此类推。
GETRANGE 通过保证子字符串的值域(range)不超过实际字符串的值域来处理超出范围的值域请求。
note:
GETRANGE命令在 Redis 2.0 之前的版本里面被称为SUBSTR命令
| |
2.17. 命令的时间复杂度
字符串这些命令中,除了del、mset、mget支持多个键的批量操作,时间复杂度和键的个数相关,为O(n),getrange和字符串长度相关,也是O(n),其余的命令基本上都是O(1)的时间复杂度,所以操作速度非常快
3. Hash 类型命令
Redis中的Hash类型可以看成具有String Key和String Value的map容器。所以该类型非常适合于存储值对象的信息。如Username、Password和Age等。如果Hash中包含很少的字段,那么该类型的数据也将仅占用很少的磁盘空间。每一个Hash可以存储4294967295个键值对。
3.1. 赋值
hset key field value:为指定的key设定field/value对(键值对)。hmset key field value [field2 value2 …]:设置key中的多个filed/value
3.2. 取值
hget key field: 返回指定的key中的field的值hmget key fileds:获取key中的多个filed的值hgetall key:获取key中的所有filed-vaule
3.3. 删除
hdel key field [field … ]:可以删除一个或多个字段,返回值是被删除的字段个数,当value都删除后,key也会删除了del key:删除对应的key的整个Hash
3.4. 增加数字
| |
- 设置 key 中 filed 的值增加 increment。如:
hincrby age 20 increment,age 增加 20
3.5. 其他命令
hexists key field:判断指定的key中的filed是否存在hlen key:获取key所包含的field的数量hkeys key:获得所有的keyhvals key:获得所有的value
4. List 类型命令
在Redis中,list类型是按照插入顺序排序的字符串链表。我们可以在其头部(left)和尾部(right)添加新的元素。在插入时,如果该key不存在,Redis将为该key创建一个新的链表。与此相反,如果链表中的所有元素都被删除了,那么该key也将会被从数据库中删除。list中可以包含的最大元素数据量4294967295(十亿以上)。
在 java 中 List 接口有常用的有 ArrayList、LinkedList,而在 redis 中的 list 就类似于 java 中的 LinkedList。
4.1. 两端添加
| |
- 在指定的 key 对应的 list 的头部插入所有的 value,如果该 key 不存在,该命令在插入之前创建一个与该 key 对应的空链表,再从头部插入数据。插入成功,返回元素的个数。
| |
- 在指定的 key 对应的 list 的尾部插入所有的 value,如果该 key 不存在,该命令在插入之前创建一个与该 key 对应的空链表,再从尾部插入数据。插入成功,返回元素的个数。
4.2. 查看列表
lrange key start end:获取链表中从start到end的元素的值,start和end从0开始计数,如果为负数,-1表示倒数第一个元素,-2表示倒数第二个元素,以此类推。- 查看所有列表:(0~-1就可以查看所有值)。例:
lrange key 0 -1

4.3. 两边弹出
| |
- 返回并弹出指定的key对应链表中头部(left)第一个元素,如果该key不存在,返回nil。
| |
- 返回并弹出指定的key对应链表中尾部(right)第一个元素,如果该key不存在,返回nil。
4.4. 获取列表中元素的个数
| |
- 返回指定 key 对应链表中元素的个数。命令的
l代表 list,len代表 length
5. Set 类型命令
Redis 中,可以将set类型看作是没有排序的字符集合,set中可以包含的最大元素数据量4294967295(十亿以上)。
和list不同,set集合不允许出现重复元素,如果多次添加相同元素,set中仅保留一份。
5.1. 添加/删除元素
sadd key value1 value2……:向set中添加数据,如果该key的值已存在,则不会重复添加,返回添加成功个数srem key value1 value2……:删除set中指定的成员,返回删除成功个数
5.2. 获得集体中的元素
smembers key:获取set集合中所有元素
- 直接删除key,那么key对应的list-set-sortedset都会删除;
- 如果key对应的所有值删除了,那么key也会自动被删除
5.3. 判断元素是否在集合中存在
sismember key value:判断key中指定的元素是否在该set集合中存在。存在则返回1,不存在则返回0
6. SortedSet 类型命令
SortedSet 和 Set 类型极为类似,它们都是字符串的集合,都不允许重复的元素出现在一个 Set 中。它们之间的主要区别是SortedSet 中每一个元素都会有一个分数(score)与之关联,Redis 正是通过分数来为集合中的元素进行从小到大的排序(默认)。
SortedSet 集合中的元素必须是唯一的,但分数(score)却是可以重复。
6.1. 添加元素
| |
- 将所有元素以及对应的分数,存放到 sortedset 集合中,如果该元素已存在则会用新的分数替换原来的分数。返回值是新加入到集合中的元素个数,不包含之前已经存在的元素。
6.2. 查询元素(从小到大)
| |
- 获取集合中下标为 start 到 end 的元素,不带分数排序之后的 SortedSet 与 list 的位置是一样,位置从左到右是正数,从0开始,位置从右到左是负数,从-1开始,-1是倒数第一个元素,-2倒数第二个元素
| |
- 获取集合中下标为 start 到 end 的元素,带分数按分数从小到大排序。如果相同用户的话,不会再将用户名插入集合中,但分数可以替换原来的分数
6.3. 查询元素(从大到小)
| |
- 按照元素分数从大到小,获取集合中下标为start到end的元素,不带分数
| |
- 按照元素分数从大到小,获取集合中下标为start到end的元素,带分数
6.4. 获取元素分数
| |
- 返回指定元素的分数
6.5. 获取元素数量
| |
- 获取集合中元素数量
6.6. 删除元素
| |
- 从集合中删除指定的元素
6.7. 按照分数范围删除元素
| |
- 按照分数范围删除元素
7. Redis 其他命令(了解)
7.1. pipeline 批命令
Redis 客户端执行一条命令分4个过程:发送命令、命令排队、命令执行、返回结果。使用 pipeline 可以批量请求,批量返回结果,将多次 IO 往返的时间缩减为一次,执行速度比逐条执行要快。使用时有以下注意事项:
- 使用
pipeline执行的指令之间没有因果相关性。因为pipeline命令是非原子性,即pipeline命令中途异常退出,之前执行成功的命令不会回滚。 - 使用
pipeline组装的命令个数不能太多,不然数据量过大,增加客户端的等待时间,还可能造成网络阻塞,可以将大量命令的拆分多个小的pipeline命令完成。
原生批命令(mset和mget)与 pipeline 对比:
- 原生批命令是原子性;
pipeline是非原子性。 - 原生批命令只有一个命令;但
pipeline支持多命令。
7.2. 服务器命令
ping,测试连接是否存活。停止 redis 服务器再测试此命令:
| |
echo,在命令行打印一些内容。quit,退出连接。info,获取服务器的信息和统计。flushdb,删除当前选择数据库中的所有key。flushall,删除所有数据库中的所有key。
7.3. 消息订阅与发布
subscribe:订阅指定的一个频道的信息。例如,subscribe mychat,订阅“mychat”这个频道psubscribe:订阅一个或多个符合指定模式的频道。例如,psubscribe s*:批量订阅以“s”开头的频道unsubscribe:取消订阅指定的频道pubsub:查看订阅与发布系统的状态publish:在指定的频道中发布消息。例如,publish mychat 'today is a newday'
7.4. redis 事务
7.4.1. multi 开启事务
| |
- 开启事务,用于标记事务的开始,其后执行的命令都将被存入命令队列,直到执行
EXEC命令时,这些命令才会被原子的执行,类似与关系型数据库中的:begin transaction
7.4.2. exec 提交事务
| |
- 提交事务,会执行所有事务块内的命令。类似与关系型数据库中的:commit
示例:
| |
7.4.3. discard 事务回滚
| |
- 事务回滚,清空事务队列,并放弃执行事务块内的所有命令,并且客户端会从事务状态中退出。类似与关系型数据库中的:rollback
7.4.4. watch 监听键
| |
- 监视一个(或多个)key,如果在事务执行之前这个(或这些)key 被其他命令改动,那么事务将被打断(类似于乐观锁)。另外执行
EXEC命令之后,也会自动取消监控。
使用示例:
| |
示例命令实现说明:
watch name开启了对name这个 key 的监控- 修改
name的值 - 开启事务 a
- 在事务 a 中设置了
name和gender的值 - 使用
EXEC命令进提交事务 - 使用命令
get gender发现不存在,即事务 a 没有执行
7.4.5. unwath 取消所有控制
| |
- 取消
watch命令对所有 key 的监控,所有监控锁将会被取消。
8. LUA 脚本
8.1. 概述
Redis 通过 LUA 脚本创建具有原子性的命令:当 lua 脚本命令正在运行的时候,不会有其他脚本或 Redis 命令被执行,实现组合命令的原子操作。
lua 脚本作用:
- Lua 脚本在 Redis 中是原子执行的,执行过程中间不会插入其他命令。
- Lua 脚本可以将多条命令一次性打包,有效地减少网络开销。
8.2. Lua 脚本的使用
在 Redis 中执行 Lua 脚本有两种方法:eval 和 evalsha。eval 命令使用内置的 Lua 解释器,对 Lua 脚本进行求值。
| |
8.3. 应用场景
8.3.1. 限制接口访问频率(未验证正确性)
在 Redis 维护一个接口访问次数的键值对,key 是接口名称,value 是访问次数。每次访问接口时,会执行以下操作:
- 通过 aop 拦截接口的请求,对接口请求进行计数,每次进来一个请求,相应的接口访问次数 count 加 1,存入 redis。
- 如果是第一次请求,则会设置
count=1,并设置过期时间。因为这里set()和expire()组合操作不是原子操作,所以需要引入 lua 脚本实现原子操作,避免并发访问问题。 - 如果给定时间范围内超过最大访问次数,则会抛出异常。
| |
Notes: 这种接口限流的实现方式只是示例,实现比较简单,问题也比较多,一般不会使用,接口限流用的比较多的是令牌桶算法和漏桶算法。

