
redis 如何限制用户频次?
目前的是 tomcat 集群,然后会有多个任务 id,同时需要限制用户 id 频次,比如 每人每天展示 5 次
现在的 redis 结构限制频次会丢一些 (第一个图)
现在要改成精准控制频次,目前我想到的方案是 (第二个图)
这个方案倒是可以满足需求,有两个不足的点
因为涉及到多个任务 id,就会使用多个 hash,然后导致任务 id 和用户 id(key)过多,这样是不是会占用一倍的 redis 内存空间? 多个相同的用户 id 如何才能让它存一份数据,其他的用指针?
之前没用过 lua 脚本,这个性能如何?

1 gj69B3S92SZZ6767 2024-11-12 10:47:24 +08:00 为什么不考虑使用 Redis 的 INCR+ EXPIRE 来实现限流功能呢? |
2 admol 2024-11-12 10:48:03 +08:00 参考如何设计一个分布式限流器: https://jingling.im/posts/design-a-rate-limiter |
3 ddonano 2024-11-12 10:57:41 +08:00 Redisson |
4 chenfang OP @gongguowei02 是个好方法, 多个用户 id 和任务 id 增加内存占用 这个貌似还是解决不了 |
8 gj69B3S92SZZ6767 2024-11-12 15:07:59 +08:00 @admol 大佬 merge 我的 pr 了,满意 ![]() |
9 nice2cu 2024-11-12 15:10:32 +08:00 你目的是想 获取 map 、map 值变更 这两步做成原子操作吗 lua 脚本应该可以的吧 |
10 chenfang OP @nice2cu 可以变结构 ,map 中的 map 如果用 lua 涉及到第二个 map 序列话问题,再有就是 lua 脚本会锁整个 redis 实例 这两点来说 两个 map 嵌套不是一个好的方案,如果要精准限制频次的话 |
11 Goooooos 2024-11-12 15:48:12 +08:00 key: 用户 id_任务 id_日期 incr key ,incr 如果结果=1 ,就执行 expire 。 lua 脚本都没啥必要 |
12 admol 2024-11-12 15:54:38 +08:00 @gongguowei02 谢谢,不是大佬,只是老,有问题可以随时提 ![]() |
13 edward1987 2024-11-12 16:01:55 +08:00 hash_{任务 id}_{日期} key 用户 id 你这个需求不用保存历史记录的吧,每天删一删之前的,根本不用考虑内存问题了 |
14 edward1987 2024-11-12 16:04:06 +08:00 或者 hash_{用户 id}_{日期} key 任务 id 这种更推荐,因为大表按理来说更占内存,也满足你 [多个相同的用户 id 如何才能让它存一份数据] 这个需求 |
15 chenfang OP @edward1987 #14 大表按理来说更占内存 能解释一下这个么? 另外什么是大表? |
17 edward1987 2024-11-12 16:13:24 +08:00 @chenfang 指的 hash 表,大表就是 key 很多的表,也就是按 任务 id 做表名的表,因为扩容的时候是乘以 2 这样去扩容的,所以会占用更多内存。 |
18 archxm 2024-11-12 16:19:02 +08:00 分桶如何?根据 id 取模,然后分配到特定服务器来处理。非陪到的服务器,从 redis 取数据。判断频次。单台机器,就好做数据冲突处理了吧 |
20 chenfang OP @archxm #18 忘记说了 现在 redis 是集群的 使用 hash 是需要分桶 如果不是 hash 那就会分到不同的实例了 |
21 archxm 2024-11-12 17:33:51 +08:00 @chenfang #20 不管 redis 是啥,你后台服务器几台呢?如果多台,就先按用户 id 分桶,用户肯定每次固定分配到一台服务器。 然后用户分到一台服务器后,你的服务器是多线程或多进程吗?然后你可以在服务器上设置线程池或进程池,来定死用户到固定线程(或进程)上来处理,这样不会发生冲突。不用管具体存到 redis 哪个分片 |
22 ychost 2024-11-12 19:28:49 +08:00 疲劳度控制问题是吧,设置好数据过期时间应该费不了多少内存 |