@@ -847,6 +847,8 @@ spring:
847847
848848 在控制台的`Exchanges`页面,添加交换机时可以配置交换机的`Durability`参数:
849849
850+ 设置 `durable=true`,表示**RabbitMQ 重启后交换机仍然存在**,不会丢失。
851+
850852 <img src="/assets/MessageQueue.assets/image-20240821211201804.png" alt="image-20240821211201804" style="zoom:50%;">
851853
852854 > SpringAMQP创建的交换机默认持久化
@@ -868,6 +870,8 @@ spring:
868870
8698712. **队列持久化**
870872
873+ 设置 `durable=true`,表示**RabbitMQ 重启后队列还存在**(队列结构保留),不会丢失。
874+
871875 SpringAMQP创建的队列默认持久化
872876
873877 ` ` ` java
@@ -903,8 +907,10 @@ spring:
903907
9049083. **消息持久化**
905909
906- SpringAMQP创建的消息默认持久化
910+ 消息在发送时,设置 `deliveryMode=2`(持久化模式),表示消息会**写入磁盘**,即使 RabbitMQ 异常宕机也能恢复。
907911
912+ SpringAMQP创建的消息默认持久化
913+
908914 ` ` ` java
909915 @Test
910916 public void testSendMap() throws InterruptedException {
@@ -916,7 +922,7 @@ spring:
916922 rabbitTemplate.convertAndSend("object3.queue", msg);
917923 }
918924 ` ` `
919-
925+
920926 <img src="/assets/MessageQueue.assets/image-20240821211717209.png" alt="image-20240821211717209" style="zoom:67%;">
921927
922928# ### 4.2.2 LazyQueue
@@ -1145,7 +1151,7 @@ spring:
11451151
11461152<img src="/assets/MessageQueue.assets/image-20240824155020808.png" alt="image-20240824155020808" style="zoom:80%;">
11471153
1148- 当然,上述极端情况发生的概率还是非常低的,不过不怕一万就怕万一。为了应对上述情况Spring又提供了消费者失败重试机制 :在消费者出现异常时利用本地重试,而不是无限制的requeue到mq队列。
1154+ 当然,上述极端情况发生的概率还是非常低的,不过不怕一万就怕万一。为了应对上述情况Spring又提供了**消费者失败重试机制 :在消费者出现异常时利用本地重试** ,而不是无限制的requeue到mq队列。
11491155
11501156` ` ` yaml
11511157spring:
@@ -1283,7 +1289,25 @@ spring:
12831289- 开启消费者确认机制为auto,由spring确认消息处理成功后返回ack,异常时返回nack
12841290- 或者开启消费者失败重试机制,并设置MessageRecoverer,多次重试失败后将消息投递到异常交换机,交由人工处理
12851291
1286- # ## 4.4 业务幂等性处理
1292+ # ## 4.4 兜底方案
1293+
1294+ 核心在于**主动查询**。
1295+
1296+ 例如:既然MQ通知不一定发送到交易服务,那么交易服务就必须自己**主动去查询**支付状态。这样即便支付服务的MQ通知失败,我们依然能通过主动查询来保证订单状态的一致。
1297+
1298+ <img src="/assets/MessageQueue.assets/image-20240824165411656.png" alt="image-20240824165411656" style="zoom:80%;">
1299+
1300+ > 那么问题来了,我们到底该在什么时间主动查询支付状态呢?
1301+ >
1302+ > 这个时间是无法确定的,因此,通常我们采取的措施就是利用**定时任务**定期查询,例如每隔20秒就查询一次,并判断支付状态。如果发现订单已经支付,则立刻更新订单状态为已支付即可。
1303+
1304+ 综上,支付服务与交易服务之间的订单状态一致性是如何保证的?
1305+
1306+ - 首先,支付服务会正在用户支付成功以后利用MQ消息通知交易服务,完成订单状态同步。
1307+ - 其次,为了保证MQ消息的可靠性,我们采用了生产者确认机制、消费者确认、消费者失败重试等策略,确保消息投递的可靠性
1308+ - 最后,我们还在交易服务设置了定时任务,定期查询订单支付状态。这样即便MQ通知失败,还可以利用定时任务作为兜底方案,确保订单支付状态的最终一致性。
1309+
1310+ # # 5. 业务幂等性处理
12871311
12881312何为幂等性?
12891313
@@ -1309,7 +1333,7 @@ spring:
13091333- 唯一消息ID
13101334- 业务状态判断
13111335
1312- # ### 4.4 .1 唯一消息ID
1336+ # ## 5 .1 唯一消息ID
13131337
13141338思路:
13151339
@@ -1338,7 +1362,7 @@ public MessageConverter messageConverter(){
13381362
13391363> 意思就是,SpringAMOP帮你写好了新建MessageId的代码,但是利用MessageId实现业务幂等需要自己写
13401364
1341- # ### 4.4 .2 业务判断
1365+ # ## 5 .2 业务判断
13421366
13431367业务判断就是基于业务本身的逻辑或状态来判断是否是重复的请求或消息,不同的业务场景判断的思路也不一样。
13441368
@@ -1365,23 +1389,7 @@ public MessageConverter messageConverter(){
13651389 }
13661390` ` `
13671391
1368- # ## 4.5 兜底方案
1369-
1370- 核心在于**主动查询**。
1371-
1372- 例如:既然MQ通知不一定发送到交易服务,那么交易服务就必须自己**主动去查询**支付状态。这样即便支付服务的MQ通知失败,我们依然能通过主动查询来保证订单状态的一致。
1373-
1374- <img src="/assets/MessageQueue.assets/image-20240824165411656.png" alt="image-20240824165411656" style="zoom:80%;">
13751392
1376- > 那么问题来了,我们到底该在什么时间主动查询支付状态呢?
1377- >
1378- > 这个时间是无法确定的,因此,通常我们采取的措施就是利用**定时任务**定期查询,例如每隔20秒就查询一次,并判断支付状态。如果发现订单已经支付,则立刻更新订单状态为已支付即可。
1379-
1380- 综上,支付服务与交易服务之间的订单状态一致性是如何保证的?
1381-
1382- - 首先,支付服务会正在用户支付成功以后利用MQ消息通知交易服务,完成订单状态同步。
1383- - 其次,为了保证MQ消息的可靠性,我们采用了生产者确认机制、消费者确认、消费者失败重试等策略,确保消息投递的可靠性
1384- - 最后,我们还在交易服务设置了定时任务,定期查询订单支付状态。这样即便MQ通知失败,还可以利用定时任务作为兜底方案,确保订单支付状态的最终一致性。
13851393
13861394# # 5. 延迟信息
13871395
0 commit comments