关于消息推送方案的讨论 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ben548
V2EX    Redis

关于消息推送方案的讨论

  • &nbp;
  •   ben548 2023-07-04 14:32:30 +08:00 2990 次点击
    这是一个创建于 904 天前的主题,其中的信息可能已经有所发展或是发生改变。
    背景:运营可以配置无上限的活动,在活动列表和详情中,用户可以进行关注,关注后需要在活动开始前 15 分钟向推送活动开始的通知消息。
    当前方案:创建完活动之后向延迟队列中投递一个执行时间为(活动开始时间-15 分钟)的任务,目前关注用户存储在 redis 的 zset 中,向延迟队列中投递的是活动的 id 信息,延迟队列消费到这条消息的时候,从关注的用户 zset 中拉取用户 id 进行消息推送。
    延迟队列的设计:目前是依赖 redis ,生产者向 redis 的 zset 中投递 task 信息,score 是活动的通知时间(活动开始时间-15 分钟),然后轮询这个 task 的 redis key ,读取到期是任务信息,读取到之后将该任务信息投递到 redis 的 list (通过 rpush )中,消费者则一直读取这个 list 队列(通过 lpop )。
    目前想探讨的是:这个方案是否在活动很多的时候导致推送消息的延迟(虽然可以通过增加消费者来缓解,正常哪怕是一个活动有百万级别的活动关注者(极其罕见),从 redis 的 zset 中分页拉取出来并投递消息,一般处理时长不会超过 10 分钟)
    但是隐隐约约还是觉得是不是还有更好的方案呢?可以尽量减少延迟的方案。
    13 条回复    2023-07-05 17:43:34 +08:00
    mineralsalt
        1
    mineralsalt  
       2023-07-04 14:40:27 +08:00
    轮询 redis 真的是太不优雅了, 不如扔一个 RocketMQ 延时消息, 消费者线程弄多些, 消费起来会很快
    ben548
        2
    ben548  
    OP
       2023-07-04 14:42:23 +08:00
    @mineralsalt 确实,但是公司目前只有 kafka 这一个 mq ,如果有类似 rabbitmq 那样的组件,那处理起来就很容易很简单了(当然也是依赖加消费者。。。)
    npe
        3
    npe  
       2023-07-04 15:12:51 +08:00
    Redis 的队列谨慎使用,ack 不好搞。用 Kafka 、RocketMQ ,多搞几个 consumer 即可。另外消息推送,可以降低下消息 priority 。
    beryl
        4
    beryl  
       2023-07-04 15:20:27 +08:00
    正常用 1#的 rocketMQ 延时消息基本可以满足。
    没做过类似的业务,不过想到另一个方案,是不是可以提前推送到客户端,假设业务是可以至少提前半小时配置号消息的,然后客户端去校验本地的消息队列中的数据。

    需要考虑:消息临时撤销、内容变更如何解决(客户端推送之前查询?如果一千万客户端,一分钟之内本地推送完成,推送之前查询下消息是否生效以及消息内容,服务端接口 QPS:16 万,对于一千万客户端的程序来说应该可以接受
    rockddd
        5
    rockddd  
       2023-07-04 15:29:28 +08:00
    我是用 rabbitmq 延迟消息插件解决的。消费者监听死信队列,开线程池处理消息
    wqhui
        6
    wqhui  
       2023-07-04 15:43:38 +08:00
    如果不是必须实时投递的话,把消息带上生效时间提前扔下去,用户端筛选出到时间的来提示
    rabbitmq 的延时队列其实也有个问题,同一条队列消息到期时间必须是递增的,即队列头消息必须先于队列其他消息过期才能正常使用,否则会阻塞,这种况下只能保证不早设置的时刻取到消息。对于过期时长不是固定的,最好是分队列
    LeegoYih
        7
    LeegoYih  
       2023-07-04 15:46:14 +08:00
    基于延时队列是最常见的做法。

    问问产品接不接受本地消息推送,比如活动是 10:15 ,用户点击关注的时往本地设置一个 10:00 的定时任务。很多手游体力提醒都是这种方式的。
    sipt
        8
    sipt  
       2023-07-04 16:01:56 +08:00
    Redis Keyspace Notifications 也许能给点灵感
    vitoliu
        9
    vitoliu  
       2023-07-05 00:12:35 +08:00
    你的设计好在简单,能够快速迭代,代码也直观。小活动、用户量少推送起来不费力。
    大流量不建议。
    N 个用户关注了 M 个活动,你的存储底线需要存 N x M 个数据。重试和断点续推的能力为 0 。
    一般订阅活动后,客户端会起任务定时拉任务状态即可。
    如果是服务端统一做这事儿一条条推,还是推荐 MQ 可靠性会高一些。
    nealHuang
        10
    nealHuang  
       2023-07-05 09:18:57 +08:00
    可以嫖 zookeeper 的 过期桶队列源码过来?
    starxg
        11
    starxg  
       2023-07-05 12:41:47 +08:00
    ben548
        12
    ben548  
    OP
       2023-07-05 17:43:06 +08:00
    @starxg 哈哈,go-zero 的延迟队列貌似用了这个组件
    ben548
        13
    ben548  
    OP
       2023-07-05 17:43:34 +08:00
    @nealHuang 大佬的方案有点高端啊。。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1510 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 40ms UTC 16:36 PVG 00:36 LAX 08:36 JFK 11:36
    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