假設商品和結算和支付是不一樣的系統,兩個系統之間的通信能夠經過消息隊列完成,不須要強制性的接口關聯。值得注意的是消息隊列中間件通常都支持同步和異步操做。java
一個http請求裏面若是有多線程的異步操做的話,在高併發環境下回產生大量的等待隊列,形成後果是大量的線程被佔用,內存,cup,數據庫等都會處於高負荷狀態。redis
經過消息隊列中間件將異步處理都發送到消息隊列中,而後經過推或者拉的方式執行異步處理的內容,減小了線程的佔用,也不會在請求系統中產生大量等待隊列,由於實際生產環境消息隊列中間件都會獨立一臺或者多臺服務器。算法
主要用於高併發業務場景好比秒殺。spring
將用戶請求放入消息隊列中,若是消息隊列的大小超過了設置的最大值,則直接拋棄改請求。數據庫
不少系統多會在aop層保存日誌到mongo,若是是同步操做會嚴重影響請求響應時間,即便經過線程來達到異步操做的目的也會暫用網站的大量資源,經過mq保存日誌,用獨立的日誌系統進行日誌處理會是一個好的辦法,若是設計的好的話日誌系統甚至能夠兼容多個平臺。apache
假設商品信息均保存到了redis中,若是商家後臺對商品信息進行了修改,可經過發送消息的方式告知商品信息已變動,消費端只須要經過監聽去修改響應redis中商品信息接口。json
經過消息隊列實現聊天。緩存
在實際業務中數據庫的部分字段多是冗餘字段,或者說冗餘字段的值是其它表幾個字段的值的和,此種場景數據同步可經過mq來實現數據同步,以避免相關字段的保存修改操做接口顯得不三不四服務器
1)對於重要業務最好在redis裏面保存一份copysession
2)消息回執,制定檢查機制,肯定消息 已經被執行
3)定時器,查漏補缺,特別是數據同步,緩存設置等場景
部分業務多是但願多個平臺不一樣的項目多能幹收到消息,應使用發佈訂閱模式。
有些業務涉及併發,可能須要要求一對一關係,須要控制。
以java舉例
<bean id="myDestination" class="org.apache.activemq.command.ActiveMQTopic"> <!-- 設置消息主題的名字,多個用逗號隔開 --> <constructor-arg index="0" value="chanel1,channel2,channel3,channel4" /> </bean> <!-- 消息監聽容器 --> <bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="mqFactory" /> <property name="destination" ref="myDestination"/> <property name="messageListener" ref="messageDelegateListenerImpl" /> <property name="pubSubDomain" value="true" /> <property name="pubSubNoLocal" value="false" /> </bean>
發送消息最好發送textMessage,若是是對象將對象轉換爲json字符串便可,由於textMessage能夠直接在控制檯發送,方便本身調試和測試人員進行測試。
/** * 發佈消息 * * @param channel * @param message * @date 2016年7月19日 */ public static void sendTopic(String channel, Object message) { String messageStr = ""; if (message.getClass().isAssignableFrom(String.class)) { messageStr = (String) message; } else { messageStr = JsonUtil.objectToJsonStr(message); } final String finalMessage = messageStr; try { final Topic destination = publishJmsTemplate.getConnectionFactory().createConnection().createSession(false,Session.AUTO_ACKNOWLEDGE).createTopic(channel); publishJmsTemplate.send(destination, new MessageCreator() { public Message createMessage(Session session) throws JMSException { log.info("topic name is" + destination.toString() + ",publish content is:\n" + finalMessage); TextMessage textMessage = session.createTextMessage(finalMessage); textMessage.setJMSExpiration(TimeUnit.DAYS.toSeconds(1));//發佈的消息保留一天 return session.createTextMessage(finalMessage);//text message 在mq控制檯也能夠發,便於測試和維護 } }); } catch (Exception e) { log.error("--------------添加生產隊列對象失敗" + e.toString(), e); } }
如圖,activemq控制檯僅容許發送textMessage
方案是編寫算法將消息路由到設置好的不一樣渠道,須要注意的是多渠道消費消息可能出現併發問題,注意控制,能夠將同一類型的消息或者相同的消息發送到同一個渠道,經過算法去控制併發的問題。