redis 控制用户频次问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
chenfang
V2EX    程序员

redis 控制用户频次问题

  •  
  •   chenfang 334 天前 2547 次点击
    这是一个创建于 334 天前的主题,其中的信息可能已经有所发展或是发生改变。

    redis 如何限制用户频次?

    目前的是 tomcat 集群,然后会有多个任务 id,同时需要限制用户 id 频次,比如 每人每天展示 5 次

    现在的 redis 结构限制频次会丢一些 (第一个图)

    现在要改成精准控制频次,目前我想到的方案是 (第二个图)

    这个方案倒是可以满足需求,有两个不足的点

    1. 因为涉及到多个任务 id,就会使用多个 hash,然后导致任务 id 和用户 id(key)过多,这样是不是会占用一倍的 redis 内存空间? 多个相同的用户 id 如何才能让它存一份数据,其他的用指针?

    2. 之前没用过 lua 脚本,这个性能如何?

    图 1 图 2

    22 条回复    2024-11-12 19:28:49 +08:00
    gj69B3S92SZZ6767
        1
    gj69B3S92SZZ6767  
       334 天前   1
    为什么不考虑使用 Redis 的 INCR+ EXPIRE 来实现限流功能呢?
    admol
        2
    admol  
       334 天前
    参考如何设计一个分布式限流器: https://jingling.im/posts/design-a-rate-limiter
    ddonano
        3
    ddonano  
       334 天前
    Redisson
    chenfang
        4
    chenfang  
    OP
       334 天前
    @gongguowei02 是个好方法, 多个用户 id 和任务 id 增加内存占用 这个貌似还是解决不了
    chenfang
        5
    chenfang  
    OP
       334 天前
    @ddonano 我们就是用的 redisson...
    chenfang
        6
    chenfang  
    OP
       334 天前
    @admol 我去看看这个文章
    airqj
        7
    airqj  
       334 天前
    @chenfang #4 想知道用户量有多大
    gj69B3S92SZZ6767
        8
    gj69B3S92SZZ6767  
       334 天前
    @admol 大佬 merge 我的 pr 了,满意
    nice2cu
        9
    nice2cu  
       334 天前
    你目的是想 获取 map 、map 值变更 这两步做成原子操作吗
    lua 脚本应该可以的吧
    chenfang
        10
    chenfang  
    OP
       334 天前
    @nice2cu 可以变结构

    ,map 中的 map 如果用 lua 涉及到第二个 map 序列话问题,再有就是 lua 脚本会锁整个 redis 实例

    这两点来说 两个 map 嵌套不是一个好的方案,如果要精准限制频次的话
    Goooooos
        11
    Goooooos  
       334 天前
    key: 用户 id_任务 id_日期

    incr key ,incr 如果结果=1 ,就执行 expire 。

    lua 脚本都没啥必要
    admol
        12
    admol  
       334 天前
    @gongguowei02 谢谢,不是大佬,只是老,有问题可以随时提
    edward1987
        13
    edward1987  
       334 天前
    hash_{任务 id}_{日期}
    key 用户 id
    你这个需求不用保存历史记录的吧,每天删一删之前的,根本不用考虑内存问题了
    edward1987
        14
    edward1987  
       334 天前
    或者 hash_{用户 id}_{日期}
    key 任务 id
    这种更推荐,因为大表按理来说更占内存,也满足你 [多个相同的用户 id 如何才能让它存一份数据] 这个需求
    chenfang
        15
    chenfang  
    OP
       334 天前
    @edward1987 #14 大表按理来说更占内存 能解释一下这个么? 另外什么是大表?
    chenfang
        16
    chenfang  
    OP
       334 天前
    @Goooooos 目前确实在在考虑如何不用 lua 毕竟我感觉对整体性能有不小的影响
    edward1987
        17
    edward1987  
       334 天前
    @chenfang 指的 hash 表,大表就是 key 很多的表,也就是按 任务 id 做表名的表,因为扩容的时候是乘以 2 这样去扩容的,所以会占用更多内存。
    archxm
        18
    archxm  
       334 天前
    分桶如何?根据 id 取模,然后分配到特定服务器来处理。非陪到的服务器,从 redis 取数据。判断频次。单台机器,就好做数据冲突处理了吧
    archxm
        19
    archxm  
       334 天前
    @archxm 单台机器,同样对 id 做取模分桶,用线程池解决。单个线程处理单次请求。
    chenfang
        20
    chenfang  
    OP
       334 天前
    @archxm #18 忘记说了 现在 redis 是集群的 使用 hash 是需要分桶 如果不是 hash 那就会分到不同的实例了
    archxm
        21
    archxm  
       334 天前
    @chenfang #20 不管 redis 是啥,你后台服务器几台呢?如果多台,就先按用户 id 分桶,用户肯定每次固定分配到一台服务器。
    然后用户分到一台服务器后,你的服务器是多线程或多进程吗?然后你可以在服务器上设置线程池或进程池,来定死用户到固定线程(或进程)上来处理,这样不会发生冲突。不用管具体存到 redis 哪个分片
    ychost
        22
    ychost  
       334 天前
    疲劳度控制问题是吧,设置好数据过期时间应该费不了多少内存
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     861 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 19:26 PVG 03:26 LAX 12:26 JFK 15:26
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86