在redis官方文档中,INCR命令有如下操作:
FUNCTION LIMIT_API_CALL(ip)
current = LLEN(ip)
IF current > 10 THEN
ERROR "too many requests per second"
ELSE
IF EXISTS(ip) == FALSE
MULTI
RPUSH(ip,ip)
EXPIRE(ip,1)
EXEC
ELSE
RPUSHX(ip,ip)
END
PERFORM_API_CALL()
END
Redis 官方文档描述道:请注意,我们这里有一个竞赛,但这不是问题:EXISTS 可能返回 false,但密钥可能在我们在 MULTI / EXEC 块内创建它之前由另一个客户端创建。然而,在极少数情况下,这场竞赛只会错过 API 调用,因此速率限制仍然可以正常工作。
我有一个问题。如果我同时发送1w个请求,那不是会漏掉9999个请求吗?这还能正常使用吗?
我希望有人能解决我的问题。
如何能够同时发送如此多的请求? 您需要如此数量的应用程序在同一时间发送如此数量的完全相同的请求。 所有这些都与服务器保持精确的距离,没有任何噪音,以如此精确的方式改变请求的速度,以至于所有的请求都在进入
if
块之前到达 MULTI
。
但是准确且确定的答案 — Redis 是单线程的,每个应用程序都可以在特定时间点发送一个命令,这意味着如果您的分片服务器中有多个节点正在接受写入命令,则可能会发生问题,这意味着完全相同的时间的罕见情况可能会以丢失请求而告终,与
MIN(number of nodes accept writes in the shard, app number)
相同。
但这是大学算法考试的答案,在现实世界中,错过的概率是十亿分之一,但还是不止一个。