V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ben548
V2EX  ›  Redis

关于消息推送方案的讨论

  •  
  •   ben548 · 2023-07-04 14:32:30 +08:00 · 2421 次点击
    这是一个创建于 538 天前的主题,其中的信息可能已经有所发展或是发生改变。
    背景:运营可以配置无上限的活动,在活动列表和详情中,用户可以进行关注,关注后需要在活动开始前 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 万,对于一千万客户端的程序来说应该可以接受
    wxw752
        5
    wxw752  
       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   ·   实用小工具   ·   2312 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 16:06 · PVG 00:06 · LAX 08:06 · JFK 11:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.