求助,支付系统的异步通知实现

2016-09-28 13:37:13 +08:00
 klgd

目前的实现方式:
参考支付宝的异步通知,每个订单的异步通知实行分频率发送:15s 3m 10m 30m 30m 1h 2h 6h 15h
脚本每秒请求数据库获取到时间需要发送的通知,返回成功则结束,失败则按下一个时间写入数据库,等待发送
目前的方式虽然实现了但是 1 、每秒请求有点儿浪费资源; 2 、通知方式不稳定; 3 、无法承受大数据量等等

现在想改为使用队列的方式实现,但是不知道如何实现通知返回失败,往队列里写下一次通知?
方案 1 :到下一次发送通知时间时,写入队列,队列实时处理,但不知道该如何实现到指定时间写队列
方案 2 :队列里延迟,也找到了可以实现这个延迟的队列 beanstalk,但是无法实现分布式,单台的方式公司运维不给弄,他建议用 kafka,但是 kafka 好像不可以延迟

想请教大家,异步通知是实现方案,或者上面的问题怎么解决?

11327 次点击
所在节点    程序员
27 条回复
cszchen
2016-09-28 20:32:36 +08:00
可以用 php-resque ,本身是一个队列,支持定时执行。
pubby
2016-09-28 20:49:40 +08:00
印象中 rabbitmq 貌似没有 message 的优先级,几年前用过,至少 php 的 amqp 扩展没有支持优先级设置。

rabbitmq 比较强大,能做消息系统
beanstalk 只能做队列
julyclyde
2016-09-29 11:50:14 +08:00
用什么队列其实是无所谓的

轻负载的情况下,队列长度基本保持在 0 ,也就是收到之后立刻就能处理
当队列积压的情况下,虽然没及时确认,导致支付网关假确认,但你也没更好的办法了
所以其实没啥需要担心的
jerray
2016-09-29 12:08:33 +08:00
延迟发送用 RabbitMQ 可以实现,并不需要任何 RabbitMQ 扩展。

方案:

比如说你有一个 Exchange EA ,一个队列 QA ,通过 EA 进来的消息会被分发到 QA 上, Consumer 监听着队列 QA ,一旦有消息就会被消费。
然后创建一个 15s 消息超时的延时队列 QA_deferred_15s ,设置参数 x-message-ttl 为 15000 , x-dead-letter-exchange 为 EA 。

QA 的 Consumer 消费队列消息时,如果认为需要延时重试,则把这条消息发送到 QA_deferred_15s 中。由于设置了 x-message-ttl 参数, 15 秒后, QA_deferred_15s 中的这条消息会超时。由于 x-dead-letter-exchange 设置为了 EA ,超时的消息会被发送到 EA ,再由 EA 分发给 QA 。

依次类推,创建其他延时队列。大致流程就是这样:

Publisher -> EA -> QA -> Consumer
Consumer -> QA_deferred_15s -> message timeout -> EA
Consumer -> QA_deferred_3m -> message timeout -> EA
Consumer -> QA_deferred_10m -> message timeout -> EA
...

需要在 Consumer 中改写消息,以便下次需要重试时能知道把消息丢进哪个延时队列。
klgd
2016-09-30 09:00:11 +08:00
@jerray 感谢回复,写的很详细,我让我们运维看看, RabbitMQ 没用过,不懂这块的东西
inputnames
2017-12-13 09:21:55 +08:00
楼主,请问你支付解决了吗,我也遇到同样的问题。求帮助呀
Evilk
2019-08-29 16:06:16 +08:00
@jerray 赞! 目前正打算用 RabbitMQ 来做此功能,跟你描述的完全一样,如果延迟时间相同,则可只创建一个死信队列,如果延迟时间不同,则需要为每种延迟时间创建对应的死信队列

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/309499

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX