MST

星途 面试题库

面试题:Redis如何实现固定窗口限流中的原子性保障

在Redis固定窗口限流场景下,简述如何利用Redis的特性来保障并发处理时的原子性,举例说明可能用到的命令。
40.7万 热度难度
数据库Redis

知识考点

AI 面试

面试题答案

一键面试

利用Redis特性保障并发处理原子性的方法

  1. Redis单线程特性:Redis是单线程模型,这意味着同一时间只有一个命令在执行,所以在执行限流逻辑时,只要将相关操作作为一个整体交给Redis执行,就能保证原子性。
  2. 使用事务(Multi - Exec):通过MULTI命令开启事务,将一系列限流操作(如计数、判断、更新等)放入事务中,最后用EXEC命令提交事务。在事务执行期间,Redis会将这些命令按顺序依次执行,不会被其他客户端的命令打断,从而保证了原子性。
  3. 使用Lua脚本:Redis支持执行Lua脚本,Lua脚本在Redis中也是原子执行的。将限流逻辑写成Lua脚本,然后使用EVALEVALSHA命令执行脚本。因为脚本内的所有操作在Redis内部是作为一个整体执行的,所以可以确保原子性。

可能用到的命令示例

  1. INCR命令:用于对指定键的值进行原子性递增。在限流场景中,可以用来记录当前窗口内的请求次数。例如,每次请求到达时,执行INCR keykey代表当前限流窗口的计数键。
  2. EXPIRE命令:用于设置键的过期时间。在限流场景中,结合窗口时间设置计数键的过期时间,以实现固定窗口限流。例如,设置计数键key在60秒后过期,执行EXPIRE key 60
  3. MULTI、EXEC命令:如前面所述,开启事务和提交事务。示例:
MULTI
INCR key
GET key
EXEC

这里先使用INCR递增计数,然后用GET获取当前计数,整个过程是原子的。 4. EVAL命令:执行Lua脚本。假设Lua脚本实现了限流逻辑(检查计数、判断是否超过限制、更新计数等),示例:

EVAL "local current = redis.call('INCR', KEYS[1]); if current == 1 then redis.call('EXPIRE', KEYS[1], ARGV[1]); end; if current > tonumber(ARGV[2]) then return 0; else return 1; end" 1 key 60 10

其中KEYS[1]是计数键keyARGV[1]是窗口时间60秒,ARGV[2]是限流阈值10。该脚本实现了限流逻辑,并保证了原子性。