1.什麼是ActiveMQ的持久化
爲了避免MQ服務器意外宕機後丟失數據,需要做到重啓服務器後能夠回覆消息隊列,消息系統一般會採用持久化機制來保證系統的高可用。通俗的來說就是,當服務器掛了以後,消息不會丟失的機制。
ActiveMQ的消息持久化機制有AMQ、KahaDB、JDBC和LevelDB,無論使用那種持久化方式,消息的存儲邏輯都是一致的。
整體流程如下:
發送者將消息發送出去後,消息中心或者消息服務器首先將消息存儲到本地數據文件、內存數據庫或者遠程數據庫等。再試圖將消息發送給接受者,成功則將消息從存儲中刪除,失敗則繼續嘗試發送。消息中心啓動後,需要先檢查至此那個的存儲位置是否有未成功發送的消息,如果有,則會先把存儲位置中的消息發送出去。
所有持久化配置都在conf/activemq.xml中配置,配置信息都在broker標籤內部定義。
2.各種持久化機制
(1)AMQ Message Store
AMQ是在ActiveMQ5.3之前版本默認使用的,基於日誌文件的存儲機制。
persistenceAdapter>
<!--directory:保存數據的目錄;journalMaxFileLength:保存消息的文件大小-->
amqPersistenceAdapter directory="${activemq.data}/amq" maxFileLength="32mb" />
</persistenceAdapter>
AMQ基於文件存儲形式,性能高於JDBC,寫入消息時會將消息寫入到日誌文件,正是由於順序追加寫,性能很高。而且創建了消息主鍵索引,並提供了緩存機制,進一步的提升了性能。每個日誌文件大小都有限制(默認32M,可以配置)。
當文件大小超過限制,系統會新建立一個文件,當所有的消息都消費完成,系統會刪除這個文件或者歸檔;
AMQ的主要缺點是回味每一個Destination創建一個索引,如果使用了大量的queue,索引文件會非常耗磁盤空間。
由於索引巨大,一旦Broker奔潰,恢復時重建索引會變得非常緩慢;
正是由於這些缺點,AMQ已經不再推薦使用。儘管AMQ的性能高於KaHaDB。
(2)KahaDB
KahaDB是從ActiveMQ5.4開始的默認持久化車輛。KahaDB是一個文件性數據庫。是使用內存+文件的形式來保證數據的持久化的。KahaDB的文件也可以限制大小。
KahaDB的配置如下:
<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>
這樣數據會自動同步到KahaDB目錄下。KahaDB日誌文件存儲的路徑:%activemq的安裝目錄%/data/kahadb
其中:
db-*.log,該文件是保存消息內容的文件;
db.data,該文件是保存消息的索引文件,本質上是B-Tree的實現,使用B-Tree作爲索引指向db-*.log裏面存儲的消息;
db.redo,該文件是當消息服務器宕機後,用來恢復消息的文件;
lock文件,文件表示當前獲得KahaDB讀寫權限的broker。
KahaDB的特性:
1)消息使用一個事務日誌和僅僅使用一個索引文件來存儲它所有的地址;
2)消息以B-Tree結構存儲,可以快速更新;
3)完全支持JMS事務;
4)支持多種恢復機制;
(3)JDBC
ActiveMQ使用數據庫作爲持久化,不限定具體的數據庫,可以使用任意的數據庫。下面以mysql爲例。
1)首先打開activemq.xml配置文件,首先定義mysql的數據源mysql-ds,然後在<persistenceAdapter>標籤中配置jdbcPersistenceAdapter並且引用剛纔定義的數據源mysql-ds。
<broker brokerName="test-broker" persistent="true" xmlns="http://activemq.apache.org/schema/core">
<persistenceAdapter>
<jdbcPersistenceAdapter dataSource="#mysql-ds" createTabelsOnStartUp="false">
</persistenceAdapter>
</broker>
<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://127.0.0.1/activemq?relaxAutoCommit=true" />
<property name="username" value="root" />
<property name="password" value="123456" />
<property name="maxActive" value="200" />
<property name="poolPreparedStatements" value="true" />
</bean>
dataSource指定持久化的數據庫bean,createTableOnStartUp是否在啓動的時候創建數據庫表,默認值是true,這樣每次啓動都會去創建數據庫表了,一般是第一次啓動的時候設置爲true,之後改爲false。
2)加mysql數據庫的驅動jar包到activwmq/lib的文件夾下,注意:若使用第三方連接池或是連接器(例如c3p0、druid),應同時將其jar包添加到lib文件夾下
3)重啓activemq。會自動生成如下3張表:
activemq_msgs用於存儲消息,Queue和Topic都存儲在這個表中;
activemq_acks用於存儲訂閱關係。如果是持久化Topic,訂閱者和服務器的訂閱關係在這個表保存;
activemq_lock表在集羣環境下才有用,只有一個Broker可以獲取消息,稱爲Master Broker,其他的只能作爲備份等待Master Broker不可用,纔可能成爲下一個Master Broker。這個表用於記錄哪個Broker是當前的Master Broker。
使用場景:
只有在消息必須保證有效,且絕對不能丟失的時候。使用JDBC存儲策略