ActiveMQ存儲的持久化機制

我們在使用原生ActiveMQ的API編程中,介紹ActiveMQ的使用過程中,在介紹其Point-to-Point(P2P) /點對點模式時,我們發現在該模式下消息時不會丟失的
在這裏插入圖片描述


那麼這裏是如果做到消息的持久化呢?ActiveMQ提供了幾種持久化方式:

  1. AMQ消息存儲,基於文件的存儲方式,它具有寫入速度快和容易恢復的特點。消息存儲在一個個文件中,文件的默認大小爲32M,如果一條消息的大小超過了32M,那麼這個值必須設置大一點。當一個存儲文件中的消息已經全部被消費,那麼這個文件將被標識爲可刪除,在下一個清除階段,這個文件被刪除。AMQ適用於ActiveMQ5.3之前的版本。
  2. KahaDB消息存儲,提供了容量的提升和恢復能力,是現在的默認存儲方式;KahaDB是基於文件的本地數據庫儲存形式,雖然沒有AMQ的速度快,但是它具有強擴展性,恢復的時間比AMQ短,從5.4版本之後KahaDB做爲默認的持久化方式。
  3. JDBC消息存儲,消息基於JDBC存儲的。(JDBC Message Store with ActiveMQ Journal優化了JDBC Store消息存儲)
  4. Memory消息存儲,基於內存的消息存儲,就是消息存儲在內存中。這裏沒有動態的緩存存在,所以你必須注意設置你的broker所在的JVM和內存限制。這種方式的持久化消息只在當前JVM內有效,當重啓JVM之後會丟失持久化的消息。



這裏我們就來看一看ActiveMQ的conf路徑下的activemq配置文件,如下:
在這裏插入圖片描述
在這裏插入圖片描述


從上述可以看出,ActiveMQ默認的持久化機制爲KahaDB消息存儲,所以即使你不配置任何的KahaDB參數信息,ActiveMQ也會啓動KahaDB。這種情況下,KahaDB文件所在位置是你的ActiveMQ安裝路徑下的/data/kahadb子目錄,如下:
在這裏插入圖片描述

  • db.data 它是消息的索引文件,本質上是B-Tree(B樹),使用B-Tree作爲索引指向db-*.log裏面存儲的消息
  • db.redo 用來進行消息恢復
  • db-*.log 存儲消息內容。新的數據以APPEND的方式追加到日誌文件末尾。屬於順序寫入,因此消息存儲是比較 快的。默認是32M,達到閥值會自動遞增
  • lock 文件鎖,寫入當前獲得kahadb讀寫權限的broker ,用於在集羣環境下的競爭處理

系統中默認的kahadb的配置,只爲我們配置的directory來指定文件的路徑,其實我們還可以配置更多的屬性,如下:

  1. director: KahaDB存放的路徑,默認值activemq-data
  2. indexWriteBatchSize: 批量寫入磁盤的索引page數量,默認值爲1000
  3. indexCacheSize: 內存中緩存索引page的數量,默認值10000
  4. enableIndexWriteAsync: 是否異步寫出索引,默認false
  5. journalMaxFileLength: 設置每個消息data log的大小,默認是32MB
  6. enableJournalDiskSyncs: 設置是否保證每個沒有事務的內容,被同步寫入磁盤,JMS持久化的時候需要,默認爲true
  7. cleanupInterval: 在檢查到不再使用的消息後,在具體刪除消息前的時間,默認30000
  8. checkpointInterval: checkpoint的間隔時間,默認是5000
  9. ignoreMissingJournalfiles: 是否忽略丟失的消息日誌文件,默認false
  10. checkForCorruptJournalFiles: 在啓動的時候,將會驗證消息文件是否損壞,默認false
  11. checksumJournalFiles: 是否爲每個消息日誌文件提供checksum,默認false
  12. archiveDataLogs: 是否移動文件到特定的路徑,而不是刪除它們,默認false
  13. directoryArchive: 定義消息已經被消費過後,移動data log到的路徑,默認null
  14. databaseLockedWaitDelay: 獲得數據庫鎖的等待時間(used by shared master/slave),默認10000
  15. maxAsyncJobs: 設置最大的可以存儲的異步消息隊列,默認值10000,可以和concurrent MessageProducers設置成一樣的值。
  16. concurrentStoreAndDispatchTransactions: 是否分發消息到客戶端,同時事務存儲消息,默認true
  17. concurrentStoreAndDispatchTopics: 是否分發Topic消息到客戶端,同時進行存儲,默認true
  18. concurrentStoreAndDispatchQueues: 是否分發queue消息到客戶端,同時進行存儲,默認true



從ActiveMQ 4+版本開始,ActiveMQ就支持使用關係型數據庫進行持久化存儲——通過JDBC實現的數據庫連接。可以使用的關係型數據庫囊括了目前市面的主流數據庫。


接下來我們就來將默認的KahaDB的存儲機制改爲JDBC的形式,首先我們在conf下的activemq.xml中,將默認配置的kahbdb改成jdbc,如下
在這裏插入圖片描述


然後我們就需要配置上述指定的名爲dataSource的數據庫連接,其實爲Spring的配置是類似的,如下:
在這裏插入圖片描述

<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> 
	<property name="driverClassName" value="com.mysql.jdbc.Driver"/>      
	<property name="url" value="jdbc:mysql://127.0.0.1:3306/activemq?relaxAutoCommit=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>      
	<property name="username" value="root"/>     
	<property name="password" value="root"/>   
</bean>

注:其中url屬性值中配置的&amp;& 的轉義字符,其中第一個屬性relaxAutoCommit=true是必需的。



然後我們在本地數據中建立一個相同的數據庫名activemq即口,然後就可以啓動我們的ActiveMQ服務了,在啓動ActiveMQ之前,我們需要在ActiveMQ安裝目錄下的lib目錄下添加相關依賴jar包,就是用於上述創建和數據庫的連接使用
在這裏插入圖片描述
在這裏插入圖片描述
這裏版本沒有太大要求,但是最好保持一致,比如這裏我們引入dbcp2的包,那麼配置文件中肯定也要是dbcp2.BasicDataSource



添加完依賴jar包後,就可以啓動ActiveMQ了,然後我們就會發現在activemq數據庫中多出了三種表,如下:
在這裏插入圖片描述


  • ACTIVEMAQ_ACKS,用於存儲訂閱關係。如果是持久化Topic,訂閱者和服務器的訂閱關係在這個表保存
    在這裏插入圖片描述
    • CONTAINER: 消息的目的地Destination
    • SUB_DEST: 如果是使用static集羣,這個字段會有集羣其他系統的信息
    • CLIENT_ID: 每個訂閱者都必須有一個唯一的客戶端id用以區分
    • SUB_NAME: 訂閱者名稱
    • SELECTOR: 選擇器,可以選擇只消費滿足條件的消息。條件可以用自定義屬性實現,可支持多屬性and和or操作
    • LAST_ACKED_ID: 記錄消費過的消息的ID



  • ACTIVEMQ_LOCK,在集羣環境中才有用,只有一個Broker可以獲得消息,稱爲Master Broker,其他的只能作爲備份等待Master Broker不可用,纔可能成爲下一個Master Broker。這個表用於記錄哪個Broker是當前的Master Broker。
    在這裏插入圖片描述

  • ACTIVEMQ_MSGS,用於存儲消息,Queue和Topic都存儲在這個表中
    在這裏插入圖片描述
    • ID: 自增的數據庫主鍵
    • CONTAINER: 消息的目的地Destination
    • MSGID_PROD: 消息發送者在客戶端的主鍵
    • MSGID_SEQ: 是發送消息的順序,MSGID_PROD + MSGID_SEQ可以組成JMS的MessageID
    • EXPIRATION: 消息的過期時間,存儲的是從1970-01-01到現在的毫秒數
    • MSG: 消息本體的java序列化對象的二進制數據
    • PRIORITY: 優先級,從0-9,數值越大優先級越高

這裏我們在Point-to-Point(P2P) /點對點模式下,來啓動一個消息生成者,但是不啓動消費者,然後來看看ACTIVEMQ_MSGS表的信息,如下:
在這裏插入圖片描述
這裏我們就可以看到消息生成者發送的三條數據,消費者還未進行消費,就可以在ACTIVEMQ_MSGS查看到信息,然後我們在啓動消息的消費者,該表中的三條數據就會被消費掉了(即表中數據被刪除)




JDBC Message Store with ActiveMQ Journal可以看做優化版的JDBC存儲,這種方式克服了JDBC Store的不足,JDBC存儲每次消息過來,都需要去寫庫和讀庫。而JDBC Message Store with ActiveMQ Journal使用延遲存儲數據到數據庫,當消息來到時先緩存到文件中,延遲後才寫到數據庫中。


當消費者的消費速度能夠及時跟上生產者消息的生產速度時,journal文件能夠大大減少需要寫入到DB中的消息。 舉個例子,生產者生產了1000條消息,這1000條消息會保存到journal文件,如果消費者的消費速度很快的情況 下,在journal文件還沒有同步到DB之前,消費者已經消費了90%的以上的消息,那麼這個時候只需要同步剩餘的 10%的消息到DB。 如果消費者的消費速度很慢,這個時候journal文件可以使消息以批量方式寫到DB。


其配置如下:
在這裏插入圖片描述

<persistenceFactory>
	<journalPersistenceAdapterFactory journalLogFiles="4" journalLogFileSize="32768" useJournal="true" useQuickJournal="true" dataSource="#dataSource" dataDirectory="activemq-data"/>
</persistenceFactory>



Memory內存消息存儲主要是存儲所有的持久化的消息在內存中。這裏沒有動態的緩存存在,所以你必須注意設置你的broker所在的JVM和內存限制。


這種方式的持久化消息只在當前JVM內有效,當重啓JVM之後會丟失持久化的消息。


配置方式如下:只需要將persistent屬性設爲false即可
在這裏插入圖片描述




還有一種就是AMQ消息存儲,它是一個基於文件、事務存儲設計爲快速消息存儲的一個結構,該結構是以流的形式來進行消息交互的。

其配置如下:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章