<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
訊息堆積的產生場景:
1、生產者使用訊息確認機制保證訊息百分之百能夠將訊息投遞到MQ成功。
2、MQ伺服器端應該將訊息持久化到硬碟
3、消費者使用手動ack機制確認訊息消費成功
如果MQ伺服器容量滿了怎麼辦?
使用死信佇列將訊息存到資料庫中去,後期補償消費。
RabbitMQ死信佇列俗稱,備胎佇列;訊息中介軟體因為某種原因拒收該訊息後,可以轉移到死信佇列中存放,死信佇列也可以有交換機和路由key等。
產生背景:
程式碼案例:
maven依賴
<dependencies> <!-- springboot-web元件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 新增springboot對amqp的支援 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <!--fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.49</version> </dependency> </dependencies>
yml設定
server: # 服務啟動埠設定 port: 8081 servlet: # 應用存取路徑 context-path: / spring: #增加application.druid.yml 的組態檔 # profiles: # active: rabbitmq rabbitmq: ####連線地址 host: www.kaicostudy.com ####埠號 port: 5672 ####賬號 username: kaico ####密碼 password: kaico ### 地址 virtual-host: /kaicoStudy ###模擬演示死信佇列 kaico: dlx: exchange: kaico_order_dlx_exchange queue: kaico_order_dlx_queue routingKey: kaico.order.dlx ###備胎交換機 order: exchange: kaico_order_exchange queue: kaico_order_queue routingKey: kaico.order
佇列設定類
@Configuration public class DeadLetterMQConfig { /** * 訂單交換機 */ @Value("${kaico.order.exchange}") private String orderExchange; /** * 訂單佇列 */ @Value("${kaico.order.queue}") private String orderQueue; /** * 訂單路由key */ @Value("${kaico.order.routingKey}") private String orderRoutingKey; /** * 死信交換機 */ @Value("${kaico.dlx.exchange}") private String dlxExchange; /** * 死信佇列 */ @Value("${kaico.dlx.queue}") private String dlxQueue; /** * 死信路由 */ @Value("${kaico.dlx.routingKey}") private String dlxRoutingKey; /** * 宣告死信交換機 * * @return DirectExchange */ @Bean public DirectExchange dlxExchange() { return new DirectExchange(dlxExchange); } /** * 宣告死信佇列 * * @return Queue */ @Bean public Queue dlxQueue() { return new Queue(dlxQueue); } /** * 宣告訂單業務交換機 * * @return DirectExchange */ @Bean public DirectExchange orderExchange() { return new DirectExchange(orderExchange); } /** * 繫結死信佇列到死信交換機 * * @return Binding */ @Bean public Binding binding() { return BindingBuilder.bind(dlxQueue()) .to(dlxExchange()) .with(dlxRoutingKey); } /** * 宣告訂單佇列,並且繫結死信佇列 * * @return Queue */ @Bean public Queue orderQueue() { // 訂單佇列繫結我們的死信交換機 Map<String, Object> arguments = new HashMap<>(2); arguments.put("x-dead-letter-exchange", dlxExchange); arguments.put("x-dead-letter-routing-key", dlxRoutingKey); return new Queue(orderQueue, true, false, false, arguments); } /** * 繫結訂單佇列到訂單交換機 * * @return Binding */ @Bean public Binding orderBinding() { return BindingBuilder.bind(orderQueue()) .to(orderExchange()) .with(orderRoutingKey); } }
死信佇列消費者
@Component public class OrderDlxConsumer { /** * 死信佇列監聽佇列回撥的方法 * @param msg */ @RabbitListener(queues = "kaico_order_dlx_queue") public void orderDlxConsumer(String msg) { System.out.println("死信佇列消費訂單訊息" + msg); } }
普通佇列消費者
@Component public class OrderConsumer { /** * 監聽佇列回撥的方法 * * @param msg */ @RabbitListener(queues = "kaico_order_queue") public void orderConsumer(String msg) { System.out.println("正常訂單消費者訊息msg:" + msg); } }
後臺佇列管理頁面如下:
部署方式:死信佇列不能夠和正常佇列存在同一個伺服器中,應該分伺服器存放。
訂單30分鐘未支付,系統自動超時關閉的實現方案。
基於任務排程實現,效率是非常低。
基於redis過期key實現,key失效時會回撥使用者端一個方法。
使用者下單的時候,生成一個令牌(有效期)30分鐘,存放到我們redis;缺點:非常冗餘,會在表中存放一個冗餘欄位。
基於mq的延遲佇列(最佳方案)rabbitmq情況下。
原理:在我們下單的時候,往mq投遞一個訊息設定有效期為30分鐘,但該訊息失效的時候(沒有被消費的情況下),執行我們使用者端一個方法告訴我們該訊息已經失效,這時候查詢這筆訂單是否已經支付。
實現邏輯:
主要使用死信佇列來實現。
想要的程式碼:就是正常的消費者不消費訊息,或者沒有正常的消費者,在設定的時間後進入死信佇列中,然後死信消費者實現相應的業務邏輯。
當消費者業務邏輯程式碼中,丟擲異常自動實現重試 (預設是無數次重試)
應該對RabbitMQ重試次數實現限制,比如最多重試5次,每次間隔3s;重試多次還是失敗的情況下,存放到死信佇列或者存放到資料庫表中記錄後期人工補償。因為重試失敗次數之後,佇列會自動刪除這個訊息。
訊息重試原理: 在重試的過程中,使用aop攔截我們的消費監聽方法,也不會列印這個錯誤紀錄檔。如果重試多次還是失敗,達到最大失敗次數的時候才會列印錯誤紀錄檔。
如果消費多次還是失敗的情況下:
1、自動刪除該訊息;(訊息可能丟失)
解決辦法:
如果充實多次還是失敗的情況下,最終存放到死信佇列;
採用表紀錄檔記,消費失敗錯誤紀錄檔的紀錄檔記錄,後期人工自動對該訊息實現補償。
消費者獲取訊息後,呼叫第三方介面(HTTP請求),但是呼叫第三方介面失敗呢?是否需要重試 ?
答:有時是因為網路異常呼叫失敗,應該需要重試幾次。
消費者獲取訊息後,應該程式碼問題丟擲資料異常,是否需要重試?
答:不需要重試,程式碼異常需要重新修改程式碼釋出專案。
第一步、springboot專案設定需要開啟ack模式
acknowledge-mode: manual
第二步、消費者Java程式碼
int result = orderMapper.addOrder(orderEntity); if (result >= 0) { // 開啟訊息確認機制 channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); }
什麼是訊息冪等性?MQ消費者如何保證冪等性?
產生的原因:就是因為消費者可能會開啟自動重試,重試過程中可能會導致消費者業務邏輯程式碼重複執行。此刻訊息已經消費了,因為業務報錯導致訊息重新消費,這時會出現
解決方案:採用訊息全域性id根據業務來定,根據業務id(全域性唯一id)消費者可以判斷這條訊息已經消費了。
消費者程式碼邏輯:
分散式事務:在分散式系統中,因為跨服務呼叫介面,存在多個不同的事務,每個事務都互不影響。就存在分散式事務的問題。
解決分散式事務核心思想:資料最終一致性。
分散式領域中名詞:
強一致性 :要麼同步速度非常快或者採用鎖的機制 不允許出現髒讀;
強一致性解決方案:要麼資料庫A非常迅速的將資料同步給資料B,或者資料庫A沒有同步完成之前資料庫B不能夠讀取資料。
弱一致性: 允許讀取的資料為原來的髒資料,允許讀取的結果不一致性。
最終一致性: 在我們的分散式系統中,因為資料之間同步通過網路實現通訊,短暫的資料延遲是允許的,但是最終資料必須要一致性。
基於RabbitMQ解決分散式事務的思路:(採用最終一致性的方案)
解決思路圖:核心是利用mq傳送訊息給其他系統將資料修改回來。
到此這篇關於Java RabbitMQ詳解常見問題的解決的文章就介紹到這了,更多相關Java RabbitMQ內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45