实施配额系统以限制基于Web的应用程序中的请求。

huangapple go评论68阅读模式
英文:

Implementing a quota system to limit requests in a web based app

问题

我想限制我的用户每小时/每天/无论何时的请求数为25k。

我的第一个想法是简单地使用MySQL,在用户表中有一个列来存储请求,并且每次用户发出请求时递增这个计数器。但是,这种方法的问题是有时候会同时写入同一列,从而导致MySQL发生死锁,所以这不是一个好的方法,对吗?

另一种方法是,不是递增一个列的计数器,而是在一个单独的表中插入日志记录,然后对于给定的时间段计算这些记录的数量,但是这样你可能会得到一个拥有数百万条记录的表,查询可能会太慢。

当使用关系型数据库管理系统时,还需要考虑的一个方面是,每次请求都需要从数据库中计算用户的配额,这可能需要一些时间,具体取决于上述方法中的任何一种。

我的第二个想法是,我考虑使用类似Redis/Memcached(不确定是否有其他替代方案或哪个更快)的东西来存储请求计数器。这样查询和递增计数器的速度将足够快,肯定比关系型数据库快,但是我还没有尝试过处理大量数据,所以我还不确定它的性能如何。

我的第三个想法是,我会将配额数据保存在内存中的一个映射中,类似于map[int]int,其中键是用户ID,值是配额使用情况,并且我会用互斥锁保护映射的访问。这将是所有解决方案中最快的,但是如果应用程序由于某种原因崩溃,那么如果某个用户的请求数量相关的数据丢失了,你该怎么办?一种方法是在应用程序崩溃时捕获它,并循环遍历映射并更新数据库。这种方法可行吗?

我不确定上述任何一种方法是否是正确的方法,但我愿意听取建议。

英文:

I want to limit my users to 25k/requests per hour/day/whatever.

My first idea was to simply use mysql and have a column in the users table where i would store the requests and i would increment this counter each time the user makes a request. Problem with this approach is that sometimes you end up writing at the same time in the column and you get a deadlock from mysql, so this isn't really a good way to go about it, is it ?

Another way would be, instead of incrementing the counters of a column, to insert log records in a separate table and then count these records for a given timespan, but this way you can easily end up with million records table and the query can be too slow.

When using a RDBMS another aspect to take into consideration is that at each request you'd have to count the user quota from database and this can take time depending on either of the above mentioned methods.

My second idea, i thought using something like redis/memcached (not sure of alternatives or which one of them is faster) and store the request counters there. This would be fast enough to query and increment the counters, for sure faster than a RDBMS, but i haven't tried it with huge amounts of data, so i am not sure how it will perform just yet.

My third idea, i would keep the quota data in memory in a map, something like map[int]int where the key would be the user_id and the value would be the quota usage and i'd protect the map access with a mutex. This would be the fastest solution of all but then what do you do if for some reason your app crashes, you lose all that data related to the number of requests certain user did. One way would be to catch the app when crashing and loop through the map and update the database. Is this feasible?

Not sure if either of the above is the right approach, but i am open to suggestions.

答案1

得分: 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脚本可能会使事情变得更好。

英文:

I'm not sure what you mean by "get a deadlock from mysql" when you try to update a row at the same time. But a simple update rate_limit set count = count + 1 where user_id = ? should do what you want.

Personally I have had great success with Redis for doing rate limiting. There are lots of resources out there to help you understand the appropriate approach for your use case. Here is one I just glanced at that seems to handle things correctly: https://www.binpress.com/tutorial/introduction-to-rate-limiting-with-redis/155. Using pipelines (MULTI) or Lua scripts may make things even nicer.

答案2

得分: 0

你可以将map[int]int持久化到关系型数据库(RDBMS)或者文件系统中,可以定期保存,也可以在延迟函数中保存。你甚至可以将其用作缓存,而不是使用Redis。当然,相比于每个请求都连接到第三方服务,这种方式肯定会更快。此外,你可以简单地将计数器存储在用户端的cookie中。聪明的用户当然可以清除cookie,但这真的那么危险吗?你还可以在cookie中提供一些身份信息,以增加清除的不便。

英文:

You can persist your map[int]int in RDBMS or just file system time to time and in defer function. You even can use it as cache instead of redis. Surely it will be anyway faster than connection to third-party service every request. Also you can store counters on user side simply in cookies. Smart user can clear cookies of-douse but is it so dangerous at all and you can also provide some identification info in cookies to make clearing uncomfortable.

huangapple
  • 本文由 发表于 2017年1月29日 00:46:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/41912252.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定