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

支付宝那种支付回调 按一定频率推送是怎么实现的?(4m,10m,10m,1h,2h,6h,15h)

  •  
  •   wuzhizuiguo · 2020-05-26 14:24:02 +08:00 · 4824 次点击
    这是一个创建于 1668 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我的想法是, 第一次的时候直接推送(请求对方的 url) 如果成功了,那就不做其他操作. 失败了: 把推送的订单 写入 redis 的 hash 表(具体对象 )和 zset 中(主键),设置 score 值为要推送的时间,然后再加一个记录这是第几次推送的 key-value

    跑一个定时器 每秒去读 zset 中 score 符合推送的订单 id(再去 hash 中获取具体数据),并删除这两个值, 然后再次请求对方的 url,返回正常状态,那么就成功了. 失败: 根据是第几次推送, 把 score 值加大,hash 表再添加对应的订单数据. 继续推送, 直到次数太多,不再推送..

    请问下坛友, 这种回调按一定频率推送 一般是怎么做的?

    23 条回复    2020-06-02 17:16:25 +08:00
    zpfhbyx
        1
    zpfhbyx  
       2020-05-26 14:27:22 +08:00   ❤️ 1
    延时队列?
    cxshun
        2
    cxshun  
       2020-05-26 14:35:16 +08:00   ❤️ 1
    可以参考一下 RocketMQ 的实现(对,就是阿里家的),它是先把所有延迟 topic 放到几个固定的 topic 里面,根据相应的 level,比如 1,是 10s 钟啥的,然后有一个定时任务,定时检查相应的 topic 的 value,如果达到时间就把它丢到另外的 topic 中,推给相应的 client 。
    watermelon11
        3
    watermelon11  
       2020-05-26 14:43:50 +08:00   ❤️ 2
    spring-retry
    JasonLiHai
        4
    JasonLiHai  
       2020-05-26 14:46:00 +08:00   ❤️ 1
    延时队列
    jinzhongyuan
        5
    jinzhongyuan  
       2020-05-26 14:56:02 +08:00
    @cxshun 定时检查 会有延时吗?
    caryqy
        6
    caryqy  
       2020-05-26 15:00:38 +08:00   ❤️ 1
    时间轮定时器
    klgd
        7
    klgd  
       2020-05-26 16:23:14 +08:00   ❤️ 1
    RabbitMQ 的延时队列,
    向队列 A 发送一个延时 10s 的消息,RabbitMQ 对将消息放到一个类似 A.10000.x.delay 的队列里,10s 后消息会被发送到 A 队列
    你这种固定几个时间的很适合的
    wuzhizuiguo
        8
    wuzhizuiguo  
    OP
       2020-05-26 16:49:21 +08:00
    谢谢! 现在队列用的是 RabbitMQ, 如果用死信队列, 入队时间不同, 出入顺序可能会有问题(实际没有操作过). spring retry 可以重试, 但是我没有找到 可以设置 频率 类似 4m,10m,10m,1h,2h,6h,15h 这样的, 固定间隔的是可以的.
    RocketMQ 还没有使用过.
    wuzhizuiguo
        9
    wuzhizuiguo  
    OP
       2020-05-26 16:57:13 +08:00
    @klgd 如果消息在 A 队列里出来后再次失败, 这个什么时候是要放到延时 20 秒 45 秒...的死信队列里吗? (这个放到哪个队列里该怎么判断)
    意思是建立几个固定 时间的队列吗
    wizardoz
        10
    wizardoz  
       2020-05-26 16:58:52 +08:00
    klgd
        11
    klgd  
       2020-05-26 17:23:00 +08:00
    @wuzhizuiguo #9 失败后,再发送到 A 队列一个延时 20s 的消息,然后 RabbitMQ 会将消息放到一个类似 A.20000.x.delay 的队列里,20s 后消息会被发送到 A 队列,以此类推 10m 1h
    RedSpark
        12
    RedSpark  
       2020-05-26 19:49:49 +08:00   ❤️ 1
    spring try 不可靠,rabbitmq 应该是 DLQ 来实现的,调研过时不可行的。开源的方案还是 rocketmq 最靠谱。
    gabon
        13
    gabon  
       2020-05-26 20:51:09 +08:00 via Android   ❤️ 1
    qmq 支持延迟消息,可以加版本号。根据次数配置不同的延时。
    wuzhizuiguo
        14
    wuzhizuiguo  
    OP
       2020-05-27 09:19:21 +08:00
    wuzhizuiguo
        15
    wuzhizuiguo  
    OP
       2020-05-27 14:02:22 +08:00
    时间轮定时器, 我不知道是不是指 Netty 的 HashedWheelTimer. 找到几篇博客.
    ,https://russxia.com/2019/07/20/%E6%97%B6%E9%97%B4%E8%BD%AE%E5%AE%9A%E6%97%B6%E5%99%A8/
    https://www.cnblogs.com/eryuan/p/7955677.html
    https://blog.wangqi.love/articles/Java/%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E4%B8%8EHashedWheelTimer.html
    wuzhizuiguo
        16
    wuzhizuiguo  
    OP
       2020-05-27 14:53:21 +08:00
    @klgd 我能不能理解 为 消息 A 在第一次调用失败后, 进入队列 X 设置过期时间 4 分钟, 4 分钟到了, 根据死信交换器,到了队列 Y, 队列 Y 消费 发现还是调用失败, 这个时候 放到队列 Z 设置过期时间 10 分钟 ... 需要固定几个具体的队列, 例如 4 分钟队列, 10 分钟队列 10 分钟队列 2 ,1 小时队列... 每个队列 先入的过期时间也肯定会比后入的小.
    klgd
        17
    klgd  
       2020-05-27 17:04:39 +08:00
    @wuzhizuiguo #16 你客户端需要消费的只有一个队列 A,其他延时队列根据你指定的延时时间由 RabbitMQ 自行生成不同的队列,延时队列里的消息到期后还是回到了 A 队列
    对了,RabbitMQ 的延时队列是需要安装插件的
    https://github.com/rabbitmq/rabbitmq-delayed-message-exchange
    cxshun
        18
    cxshun  
       2020-05-27 17:40:06 +08:00
    @jinzhongyuan #5 这个肯定多少会有点,所以就看定时器的频率了。
    buliugu
        19
    buliugu  
       2020-05-28 09:16:28 +08:00
    简单点,beanstalkd 它不香嘛
    wuzhizuiguo
        20
    wuzhizuiguo  
    OP
       2020-05-28 09:27:23 +08:00
    @klgd 那消息回到消息队列 A 后, 再次设置过期时间, 这个怎么判断它是第几次重试 设置下次的过期时间? (要额外加判断吗)
    klgd
        21
    klgd  
       2020-05-28 10:17:04 +08:00
    @wuzhizuiguo #20 消息在入队时可以加个次数的参数,在消费消息时,处理成功了,就结束;失败了,根据次数得出下一次的延时时间,然后重新操作入队
    wuzhizuiguo
        22
    wuzhizuiguo  
    OP
       2020-05-28 10:30:01 +08:00
    @klgd 好的.(我想是加个 redis 消息主键 - 次数 这样的缓存是吧)
    wuzhizuiguo
        23
    wuzhizuiguo  
    OP
       2020-06-02 17:16:25 +08:00
    结论: rabbitMq 可行,延时队列, 不装插件情况下. 设置多个队列,例如 A,B,C,D 首先第一次调用失败, 将消息设置过期时间 4 秒, 设置缓存次数, 进入 A 队列,(A 队列固定的就是 4 秒, 不是队列本身的过期时间, 而是进入该队列的消息都是 4 秒过期. 队列中也不会出现 后入消息过期时间 比前入的早). 经过绑定的交换器 exchange 进入 实际的消费队列 X, 消费如果再失败 ,根据 redis 缓存的次数值, 在这里决定将此次消息放入到哪个队列, 假设是 B, 那么设置过期时间为 10 秒 ..... 流程就是这样, 这是我想到能实现的情况.
    rabbitMQ 方面的例子 可以根据这个博客来 https://juejin.im/post/5a12ffd451882578da0d7b3a
    谢谢.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5397 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 07:23 · PVG 15:23 · LAX 23:23 · JFK 02:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.