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

延迟队列落地方案

  •  
      awanganddong 2020-10-16 10:07:17 +08:00 3581 次点击
    这是一个创建于 1888 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求是这样的,后台配置时间,然后给用户发消息。 在用户关注后,根据这个时间发消息 比如 5s,发送一条数据 10s,发送一条数据。

    现在用的定时任务处理,这样大概会有 1 分钟左右误差。

    如果将定时任务设置成秒级,则 1s 中处理不完业务。


    如果用延迟队列。 用户关注,然后扫配置表,把用户 ID+延迟时间写入 redis zset 。然后一直消费这个有序队列。 这样存在一个问题,如果管理员修改后台配置信息,我就需要批量修改 zset 里边的时间。

    也就是需要修改整个公众号所有的 zset 数据。

    有什么简单一些的方案吗

    17 条回复    2020-10-16 14:00:28 +08:00
    coderxy
        1
    coderxy  
       2020-10-16 10:15:06 +08:00
    可以考虑配置修改只对修改后生效,前面的不管
    BBCCBB
        2
    BBCCBB  
       2020-10-16 10:15:26 +08:00
    1. redisson (用下来偶尔会有丢失的情况出现, 需要一个兜底的方案)
    2. pulsar mq 或者其他支持延迟队列的 mq.
    3. 扫表(缺点你说了).
    chogath
        3
    chogath  
       2020-10-16 10:17:15 +08:00
    redis bull - node.js
    specita
        4
    specita  
       2020-10-16 10:19:11 +08:00
    秒级扫表把需要处理的用户放入队列里串行处理
    awanganddong
        5
    awanganddong  
    OP
       2020-10-16 10:27:13 +08:00
    后台数据库如下,

    一张表存储是否开启

    公众号 是否开启是否发送信息

    还有一张子表

    记录 延迟时间 发送内容

    ------------------------------------------

    用延迟队列现在考虑的问题就是我写入 zset 数据 ,但是后台修改配置的问题。

    秒级扫表,我是以配置表为主表 。然后获取可用公众号配置项,然后循环用户表,比对用户表与配置表的差值。

    担心的问题就是在对用户表比对的过程。如果不能快速响应,那就比对失败。 因为精度是秒级别的
    Veneris
        6
    Veneris  
       2020-10-16 10:33:10 +08:00
    MQ 支持延时消费的
    axbx
        7
    axbx  
       2020-10-16 10:35:57 +08:00
    MQ 有的功能不要再折腾,大概率是比自己写的好用
    wxy1991
        8
    wxy1991  
       2020-10-16 10:43:32 +08:00
    设置一个时间的浮动值,比如第一次配置当作基准时间,比较的时候比较 基准时间+浮动时间<=>zset 的时间,修改配置时,其实是修改了浮动时间,这样就可以随意修改配置,代码改动也最小
    lidlesseye11
        9
    lidlesseye11  
       2020-10-16 10:55:31 +08:00
    Thread.sleep(5000)
    DavidNineRoc
        10
    DavidNineRoc  
       2020-10-16 11:09:38 +08:00
    来个简单一点的处理.
    发送的间隔时间 interval == 5s || 10s
    用户创建时间点 created_at
    发送延迟时间点 delay_at

    // 当用户关注之后, 往 zset 存储
    ZADD xxx delay_at "id, interval=5, created_at, "

    // 当管理员改为 20s 后, 找到最近 20s 内创建的所有用户, 重新往延时队列加
    ZADD xxx delay_at "id, interval=20, created_at, "

    // 延时队列消费的进程加一个判断.
    if interval not in 管理员的配置列表
    return false;
    lzxz1234
        11
    lzxz1234  
       2020-10-16 11:15:08 +08:00
    扫表也不一定必须有误差,每分钟扫表将要执行的放到内存队列里,到时间执行就可以了

    混合方案,也不需要额外依赖 redis 队列啥的
    sujin190
        12
    sujin190  
       2020-10-16 11:15:51 +08:00
    https://github.com/snower/forsun

    之前做的一个定时服务,通过 key 指定定时任务,通过 key 随时可以修改,每个任务秒级定时,后端持久化用 redis 不担心丢失,已经稳定用在日百万级订单超时这样的任务处理,可以看看能不能满足
    Evilk
        13
    Evilk  
       2020-10-16 11:18:49 +08:00
    RabbitMQ,本身就支持死信队列(延时队列)
    awanganddong
        14
    awanganddong  
    OP
       2020-10-16 11:23:03 +08:00
    工期紧。只能简单粗暴了
    @DavidNineRoc 这个方案可以。唯一瓶颈就是 在 zset 修改文件这里了
    mosliu
        15
    mosliu  
       2020-10-16 11:25:48 +08:00
    一个线程 定时任务,取出要发送的任务,
    另外起线程做发送不就行了。
    awanganddong
        16
    awanganddong  
    OP
       2020-10-16 12:07:01 +08:00
    理清楚了,

    最开始我困惑的点,在于后台修改配置文件,那怎么修改延迟队列的数据内容。

    刚明白过来,

    配置表修改内容后,我只需要关注添加就可以了。

    消费的时候,我验证下无效的消费就可以了。
    857681664
        17
    857681664  
       2020-10-16 14:00:28 +08:00
    rabbitMQ 的延时队列也可以处理。
    用户关注之后把 userId 放入队列,同时设置延时时间,在消费完只需要再查一次配置表,把新的延时时间设置到消息上,再把消息塞回队列即可。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5071 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 38ms UTC 05:47 PVG 13:47 LAX 21:47 JFK 00:47
    Do have faith in what you're doing.
    ubao msn 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