直播电商源码,利用Kotlin+RocketMQ 实现延时消息
直播电商源码,利用Kotlin+RocketMQ 实现延时消息的相关代码
一. 延时消息
延时消息是指消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费。
使用延时消息的典型场景,例如:
在电商系统中,用户下完订单30分钟内没支付,则订单可能会被取消。
在电商系统中,用户七天内没有评价商品,则默认好评。
这些场景对应的解决方案,包括:
轮询遍历数据库记录
JDK 的 DelayQueue
ScheduledExecutorService
基于 Quartz 的定时任务
基于 Redis 的 zset 实现延时队列。
除此之外,还可以使用消息队列来实现延时消息,例如 RocketMQ。
二. RocketMQ
RocketMQ 是一个分布式消息和流数据平台,具有低延迟、高性能、高可靠性、万亿级容量和灵活的可扩展性。RocketMQ 是2012年阿里巴巴开源的第三代分布式消息中间件。
三. RocketMQ 实现延时消息
3.1 业务背景
我们的系统完成某项操作之后,会推送事件消息到业务方的接口。当我们调用业务方的通知接口返回值为成功时,表示本次推送消息成功;当返回值为失败时,则会多次推送消息,直到返回成功为止(保证至少成功一次)。
当我们推送失败后,虽然会进行多次推送消息,但并不是立即进行。会有一定的延迟,并按照一定的规则进行推送消息。
例如:1小时后尝试推送、3小时后尝试推送、1天后尝试推送、3天后尝试推送等等。因此,考虑使用延时消息实现该功能。
3.2 生产者(Producer)
生产者负责产生消息,生产者向消息服务器发送由业务应用程序系统生成的消息。
首先,定义一个支持延时发送的 AbstractProducer。
1 | abstract class AbstractProducer :ProducerBean() {<br> var producerId: String? = null <br> var topic: String? = null <br> var tag: String?= null <br> var timeoutMillis: Int? = null <br> var delaySendTimeMills: Long? = null <br> val log = LogFactory.getLog( this .javaClass)<br> open fun sendMessage(messageBody: Any, tag: String) {<br> val msgBody = JSON.toJSONString(messageBody)<br> val message = Message(topic, tag, msgBody.toByteArray())<br> if (delaySendTimeMills != null ) {<br> val startDeliverTime = System.currentTimeMillis() + delaySendTimeMills!!<br> message.startDeliverTime = startDeliverTime<br> log.info( "send delay message producer startDeliverTime:${startDeliverTime}currentTime :${System.currentTimeMillis()}" )<br> }<br> val logMessageId = buildLogMessageId(message)<br> try {<br> val sendResult = send(message)<br> log.info(logMessageId + "producer messageId: " + sendResult.getMessageId() + "\n" + "messageBody: " + msgBody)<br> } catch (e: Exception) {<br> log.error(logMessageId + "messageBody: " + msgBody + "\n" + " error: " + e.message, e)<br> }<br> }<br> fun buildLogMessageId(message: Message): String {<br> return "topic: " + message.topic + "\n" +<br> "producer: " + producerId + "\n" +<br> "tag: " + message.tag + "\n" +<br> "key: " + message.key + "\n" <br> }<br>} |
根据业务需要,增加一个支持重试机制的 Producer
1 | @Component <br> @ConfigurationProperties ( "mqs.ons.producers.xxx-producer" )<br> @Configuration <br> @Data <br> class CleanReportPushEventProducer :AbstractProducer() {<br> lateinit var delaySecondList:List<Long><br> fun sendMessage(messageBody: CleanReportPushEventMessage){<br> //重试超过次数之后不再发事件<br> if (delaySecondList!=null) {<br> if(messageBody.times>=delaySecondList.size){<br> return<br> }<br> val msgBody = JSON.toJSONString(messageBody)<br> val message = Message(topic, tag, msgBody.toByteArray())<br> val delayTimeMills = delaySecondList[messageBody.times]*1000L<br> message.startDeliverTime = System.currentTimeMillis() + delayTimeMills<br> log.info( "messageBody: " + msgBody+ "startDeliverTime: "+message.startDeliverTime )<br> val logMessageId = buildLogMessageId(message)<br> try {<br> val sendResult = send(message)<br> log.info(logMessageId + "producer messageId: " + sendResult.getMessageId() + "\n" + "messageBody: " + msgBody)<br> } catch (e: Exception) {<br> log.error(logMessageId + "messageBody: " + msgBody + "\n" + " error: " + e.message, e)<br> }<br> }<br> }<br>} |
在 CleanReportPushEventProducer 中,超过了重试的次数就不会再发送消息了。
每一次延时消息的时间也会不同,因此需要根据重试的次数来获取这个delayTimeMills 。
通过 System.currentTimeMillis() + delayTimeMills 可以设置 message 的 startDeliverTime。然后调用 send(message) 即可发送延时消息。
以上就是 直播电商源码,利用Kotlin+RocketMQ 实现延时消息的相关代码,更多内容欢迎关注之后的文章
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现