我希望将用户限制为25k /每小时/每天/不等。
我的第一个想法是简单地使用mysql并在users表中有一个列,我将存储请求,并且每次用户发出请求时我都会递增此计数器。这种方法的问题在于,有时你最终会在列中同时写入,并且你从mysql中获得了死锁,所以这不是一个很好的方法,是吗?
另一种方法是,不是递增列的计数器,而是在单独的表中插入日志记录,然后在给定的时间跨度内计算这些记录,但这样您就可以很容易地得到百万条记录表和查询可能太慢了。
当使用RDBMS时,另一个方面需要考虑的是,在每次请求时,您都必须从数据库中计算用户配额,这可能需要时间,具体取决于上述方法之一。
我的第二个想法,我想使用像redis / memcached这样的东西(不确定替代品或哪一个更快)并在那里存储请求计数器。这对查询和递增计数器来说足够快,肯定比RDBMS快,但我没有尝试过大量的数据,所以我不确定它将如何执行。
我的第三个想法,我会将配额数据保存在地图中,例如map[int]int
,其中密钥是user_id,值将是配额使用量,我将保护地图访问权限一个互斥体。这将是最快的解决方案,但如果由于某种原因你的应用程序崩溃,你会失去所有与某些用户所做的请求数量相关的数据。一种方法是在崩溃并循环遍历地图并更新数据库时捕获应用程序。这可行吗?
不确定上述任何一种方法是否正确,但我愿意接受建议。
答案 0 :(得分:1)
当您尝试同时更新行时,我不确定“从mysql中获取死锁”是什么意思。但是简单的update rate_limit set count = count + 1 where user_id = ?
应该做你想做的事。
就我个人而言,我在Redis上取得了很大的成功率。有很多资源可以帮助您了解适用于您的用例的方法。这是我刚才看到的一个似乎处理正确的事情:https://www.binpress.com/tutorial/introduction-to-rate-limiting-with-redis/155。使用管道(MULTI
)或Lua脚本可以使事情变得更好。
答案 1 :(得分:0)
您可以将您的map[int]int
保留在RDBMS中,或者只是延迟文件系统并延迟功能。您甚至可以将其用作缓存而不是redis。当然,无论如何,每次请求都要比连接到第三方服务更快。您也可以在用户端将计数器存储在cookie中。聪明的用户可以清除-douse的cookie,但它是如此危险,你也可以在cookie中提供一些识别信息,使清除不舒服。