简单地说,我们现在是Redis
用Redis构建速率限制器很容易,因为有两个命令增加和到期.其基本概念是,您希望将请求限制在给定时间段内对特定服务的请求。假设我们有一个服务,它的用户由API密钥标识。该服务规定在任何给定的分钟内只能有20个请求。
为了实现这一点,我们希望为每分钟每个API密钥创建一个Redis密钥。为了确保我们不会用垃圾填满整个数据库,也要在一分钟后过期该键。想象一下:
用户API密钥= zA21X31,绿色表示无限,红色表示有限。
复述,关键 | zA21X31:0 | zA21X31:1 | zA21X31:2 | zA21X31:3 | zA21X31:4 |
价值 | 3. | 8 | 20. | >2 | 20. |
到期 | 最新12:02 | 最新12:03 | 最新的上午 | 最新12:05 | 最新12:06 |
时间 | 12:00 | 12:01 | 12:02 | 12:03 | 12:04 |
该密钥派生自用户API密钥,该密钥由冒号与分号连接。因为我们总是将键过期,所以我们只需要记录分钟——当小时从59转到00时,我们可以确定另外59不存在(它将提前58分钟过期)。
使用伪代码,让我们看看这是如何工作的。
1 | > [user-api-key](当前的分钟数): |
2 | 如果第1行结果小于20(或未设置),则转到第4行,否则转到第3行 |
3. | 显示错误消息并结束连接。退出。 |
4 | > OK > INCR [user-api-key]:[当前分钟数]QUEUED > EXPIRE [user-api-key]:[当前分钟数]59 QUEUED > . OK > INCR [user-api-key]:[当前分钟数 好吧 |
5 | 做服务的事情 |
从这个程序中要理解两个关键点:
最糟糕的情况是,由于一些非常奇怪和不太可能的原因,Redis服务器在INCR和EXPIRE之间死亡。当从AOF或内存复制进行恢复时,将不会恢复INCR,因为事务还没有完成。
有了这种模式,每个用户都有可能拥有两个限制键,一个是当前正在使用的,另一个将在同一分钟窗口内过期,但在其他方面它是非常有效的。