ActiveMQ中,持久化是值對消息數據的持久化。在ActiveMQ中,默認的消息是保存在內存中的。當內存容量不足的時候,或ActiveMQ正常關閉的時候,會將內存中的未處理的消息持久化到磁盤中。具體的持久化策略是kahadb。如果使用JDBC作為持久化策略,則會將所有的需要持久化的消息保存到數據庫中。
所有持久化配置都在conf/activemq.xml中配置,配置信息都在broker標簽內部定義。
一、kahadb方式
kahadb是ActiveMQ默認的持久化策略。kahadb是一個文件型數據庫。是使用內存+文件保證數據的持久化的。kahadb可以限制每個數據文件的大小。不代表總計數據容量。
1 <persistenceAdapter>
2 <!--directory:保存數據的目錄;journalMaxFileLength:保存消息的文件大小-->
3 <kahaDB directory="${activemq.data}/kahadb" journalMaxFileLength="16mb" />
4 </persistenceAdapter>
特性是:
1,日志形式存儲消息。
2,消息索引以B-Tree結構存儲,可以快速更新。
3,完全支持JMS事物
4,支持多種恢復機制
二、AMQ方式
只適用於5.3版本以前。
AMQ也是一個文件型數據庫,消息信息最終是存儲在存儲文件中的,內存中也會有緩存數據。
1 <persistenceAdapter>
2 <!--directory:保存數據的目錄;maxFileLength:保存消息的大小-->
3 <amqPersistenceAdapter directory="${activemq.data}/amq" maxFileLength="32mb" />
4 </persistenceAdapter>
性能高於JDBC,寫入消息時,會將消息寫入日志文件,由於是順序追加寫,性能很高。為了提升性能,創建消息主鍵索引,並且提供緩存機制,進一步提升性能。每個日志文件的大小都是有限制的(默認32m,可自行配置)。
當超過這個大小,系統會重新建立一個文件,當所有的消息都消費完成,系統會刪除這個文件或歸檔。
主要缺點是AMQ Message會我每一個destination創建一個索引,如果使用了大量的queue,索引文件的大小會占用很多的磁盤空間。
而且由於索引巨大,一旦Broker(ActiveMQ的應用實例)崩潰,重建索引的速度會非常慢。
雖然AMQ性能略高於Kahadb方式,但由於其重建索引時間過長,而且索引文件占用磁盤空間過大,已經不再推薦使用。
三、JDBC持久化方式
ActiveMQ將數據持久化到數據庫中,不能限定具體的數據庫,可以使用任意的數據庫,下邊我們以MySql為例。
首先打開activemq.xml配置文件,首先定義一個mysql-ds的MySql數據源,然后在persistenceAdapter節點中配置jdbcPersistenceAdapter並且引用剛才定義的數據源。
dataSource指定持久化的數據庫bean,createTableOnStartUp是否在啟動的時候創建數據庫表,默認值是true,這樣每次啟動都會去創建數據庫表了,一般是第一次啟動的時候設置為true,之后改為false。
1 <broker brokerName="test-broker" persistent="true" xmlns="http://activemq.apache.org/schema/core">
2 <persistenceAdapter>
3 <jdbcPersistenceAdapter dataSource="#mysql-ds" createTabelsOnStartUp="false">
4 </persistenceAdapter>
5 </broker>
6 <bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
7 <property name="driverClassName" value="com.mysql.jdbc.Driver" />
8 <property name="url" value="jdbc:mysql://127.0.0.1/activemq?relaxAutoCommit=true" />
9 <property name="username" value="activemq" />
10 <property name="password" value="activemq" />
11 <property name="maxActive" value="200" />
12 <property name="poolPreparedStatements" value="true" />
13 </bean>
配置成功后,需要在數據庫中創建對應的database,否則無法訪問,表格ActiveMQ可以自動創建。
數據表activemq_msgs用於存儲消息,Queue和Topic都存儲在這個表中。
ID:自增的數據庫主鍵
CONTAINER:消息的destination
MSGID_PROD:消息發送者客戶端的主鍵
MSG_SEQ:發送消息的順序,MSGID_PROD+MSG_SEQ 可以組成JMS 的MessageID
EXPIRATION:消息的過期時間,存儲的是從1970-01-01 到現在的毫秒數
MSG:消息本體的Java 序列化對象的二進制數據
PRIORITY:優先級,從0-9,數值越大優先級越高
activemq_acks 用於存儲訂閱關系。如果是持久化Topic,訂閱者和服務器的訂閱關系在這個表保存,主要的數據庫字段如下:
CONTAINER:消息的Destination
SUB_DEST:如果是使用Static 集群,這個字段會有集群其他系統的信息
CLIENT_ID:每個訂閱者都必須有一個唯一的客戶端ID 用以區分
SUB_NAME:訂閱者名稱
SELECTOR:選擇器,可以選擇只消費滿足條件的消息。條件可以用自定義屬性實現,可支持多屬性AND 和OR 操作
LAST_ACKED_ID:記錄消費過的消息的ID。
表activemq_lock 在集群環境中才有用,只有一個Broker 可以獲得消息,稱為MasterBroker,其他的只能作為備份等待Master Broker 不可用,才可能成為下一個Master Broker。這個表用於記錄哪個Broker 是當前的Master Broker。只有在消息必須保證有效,且絕對不能丟失的時候。使用JDBC 存儲策略。如果消息可以容忍丟失,或使用集群/主備模式保證數據安全的時候,建議使用levelDB或Kahadb。