一、 問題提出
場景問題:伺服器斷電重啟,未被消費的訊息是否會在重啟之後被繼續消費?
兩種選擇:非永續性模式/永續性模式非永續性模式:
伺服器斷電(關閉)之後,使用非永續性模式時,沒有被消費的訊息不會繼續消費全部丟失;
程式會報一個連線關閉異常停止執行,繼續啟動伺服器執行程式,不會接收任何訊息。永續性模式:
伺服器斷電(關閉)後,使用永續性模式時,沒有被消費的訊息會繼續消費;
程式也會報連線關閉異常,但再次啟動伺服器和程式後,接收方還能繼續原來的訊息再次接收。
二、 ActiveMQ的幾種儲存模式選擇
- AMQ訊息儲存 (預設的訊息儲存)
- 基於檔案儲存的訊息資料庫,不依賴於第三方資料庫
- KahaDB 訊息儲存(提供容量的提升和恢復能力)
- 訊息儲存機制
- JDBC 訊息儲存(訊息基於JDBC儲存)
- 使用Mysql或Oracle資料庫儲存訊息
- Memory 訊息儲存(基於內容的訊息儲存)
- ActiveMQ支援將訊息儲存到記憶體中,將Broker的“prsistent” 屬性設定為“false”。
三、本文主要記錄將ActiveMQ訊息持久化到Mysql資料庫
1. 將以下Jar包新增到到%ACTIVEMQ_HOME%\lib下面
- commons-dbcp-1.4.jar
- commons-pool-1.6.jar
- mysql-connector-java-5.1.30.jar
2. 修改ActiveMQ的conf目錄下的activemq.xml檔案,修改資料持久化的方式
在新增如下配置時,需要注意新增位置
<broker> <persistenceAdapter> <!--createTablesOnStartup="true"表示在第一次啟動時自動建立表結構,再次啟動時,應該改為false--> <jdbcPersistenceAdapter dataSource="#mysql-ds" createTablesOnStartup="true"/> </persistenceAdapter> </broker>複製程式碼
<beans>
<bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/activemq?relaxAutoCommit=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="maxActive" value="200"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
</beans>複製程式碼
3. 啟動ActiveMQ,分析資料表結構
在啟動ActiveMQ之後,會在資料庫<
activemq
>中建立三張表activemq_acks、activemq_lock、activemq_msgs
- activemq_acks:用於儲存訂閱關係。如果是持久化Topic,訂閱者和伺服器的訂閱關係在這個表儲存。
- CONTAINER:訊息的目的地
- SUB_DEST:如果是使用static叢集,這個欄位會有叢集其他系統的資訊
- CLIENT_ID:每個訂閱者客戶端ID
- SUB_NAME:訂閱者名稱
- SELECTOR:選擇器,可以選擇只消費滿足條件的訊息。條件可以用自定義屬性實現,可支援多屬性and和or操作
- LAST_ACKED_ID:記錄消費過的訊息的id。
- PRIORITY:優先順序
- XID:
- activemq_lock:用於記錄哪一個Broker是Master Broker。這張表只有在叢集環境中才會用到,在叢集中,只能有一個Broker來接收訊息,那麼這個Broker就是主Broker,其他的作為從Broker,用來備份等待。
- ID:主鍵
- TIME:時間
- BROKER_NAME:Broker名稱
- activemq_msgs:用於儲存訊息,Topic和Queue訊息都會儲存在這張表中
- ID:自增主鍵
- CONTAINER:容器名稱
- MSGID_PROD:訊息傳送者客戶端的主鍵
- MSGID_SEQ:傳送訊息的順序,msgid_prod+msg_seq可以組成jms的messageid
- EXPIRATION:訊息的過期時間,儲存的是從1970-01-01到現在的毫秒數
- MSG:訊息本體的java序列化物件的二進位制資料
- PRIORITY:優先順序,從0-9,數值越大優先順序越高