JMS學習(七)-ActiveMQ消息的持久存儲方式之KahaDB存儲


一,介紹

自ActiveMQ5.4以來,KahaDB成為了ActiveMQ默認的持久化存儲方式。相比於原來的AMQ存儲方式,官方宣稱KahaDB使用了更少的文件描述符,並且提供了更快的存儲恢復機制。

 

二,KahaDB存儲配置

在 conf/activemq.xml 中配置如下:

<broker brokerName="broker" ... >
   <persistenceAdapter>
     <kahaDB directory="activemq-data" journalMaxFileLength="32mb"/>
   </persistenceAdapter>
   ...
</broker>

<persistenceAdapter>中指定了kahaDB,並表明數據存儲在 "activemq-data"目錄下,日志文件最大長度是32MB。

比如一個實際的ActiveMQ的KahaDB存儲方式下的數據目錄如下:

可以看出,上面directory一共有四個文件:

①db.data

它是消息的索引文件。本質上是B-Tree的實現,使用B-Tree作為索引指向db-*.log里面存儲的消息。

②db.redo

主要用來進行消息恢復。

③db-*.log  存儲消息的內容。對於一個消息而言,不僅僅有消息本身的數據(message data),而且還有(Destinations、訂閱關系、事務...)

the data logs contain all of the message data and all of the information about destinations, subscriptions, transactions, etc.. 

data log以日志形式存儲消息,而且新的數據總是以APPEND的方式追加到日志文件末尾。因此,消息的存儲是很快的。比如,對於持久化消息,Producer把消息發送給Broker,Broker先把消息存儲到磁盤中(enableJournalDiskSyncs配置選項),然后再向Producer返回Acknowledge。Append方式在一定程度上減少了Broker向Producer返回Acknowledge的時間。

④lock文件

 

另外,一些關於KahaDB的配置選項如下:

1)indexWriteBatchSize  默認值1000,當Metadata Cache中更新的索引到達了1000時,才同步到磁盤上的Metadata Store中。不是每次更新都寫磁盤,而是批量更新寫磁盤,比較寫磁盤的代價是很大的。

2)indexCacheSize      默認值10000,(number of index pages cached in memory),在內存中最多分配多個頁面來緩存index。緩存的index越多,命中的概率就越大,檢索的效率就越高。

3)journalMaxFileLength  默認值32MB,當存儲的消息達到32MB時,新建一個新文件來保存消息。這個配置對生產者或消息者的速率有影響。比如,生產者速率很快而消費者速率很慢時,將它配置得大一點比較好。

4)enableJournalDiskSyncs  默認值true,默認采用同步寫磁盤,即消息先存儲到磁盤中再向Producer返回ACK

normally,the broker performs a disk sync(ensuring that a message has been physically written to disk)
before sending the ACK back to a producer

5)cleanupInterval  默認值30000ms,當消息被消息者成功消費之后,Broker就可以將消息刪除了。

6)checkpointInterval  默認值5s,每隔5s將內存中的Index(Metadata Cache)更新到磁盤的Index文件中(Metadata Store)

 

三, KahaDB存儲底層實現簡單分析

下圖是KahaDB的Architecture:

persist_01 (1)

從上圖中可以看出:圖中各個部分與KahaDB配置的存儲目錄下的文件是一 一對應的。

①在內存(cache)中的那部分B-Tree是Metadata Cache

通過將索引緩存到內存中,可以加快查詢的速度(quick retrival of message data)。但是需要定時將 Metadata Cache 與 Metadata Store同步。

這個同步過程就稱為:check point。checkpointInterval選項 決定每隔多久時間進行一次checkpoint操作。

 

②BTree Indexes則是保存在磁盤上的,稱為Metadata Store,它對應於文件db.data,它就是對Data Logs以B樹的形式 索引。

有了它,Broker(消息服務器)可以快速地重啟恢復,因為它是消息的索引,根據它就能恢復出每條消息的location。

如果Metadata Store被損壞,則只能掃描整個Data Logs來重建B樹了,這個過程是很復雜且緩慢的。

The presence of the metadata store, however, enables the broker instance to restart rapidly. 
If the metadata store got damaged or was accidentally deleted, the broker could recover by reading the data logs,
but the restart would then take a considerable length of time.

 

③Data Logs則對應於文件 db-*.log,默認是32MB

Data Logs以日志形式存儲消息,它是生產者生產的數據的真正載體。

The data logs are used to store data in the form of journals, 
where events of all kinds—messages, acknowledgments, subscriptions, subscription cancellations, transaction boundaries, etc.
---are stored in a rolling log

 

④Redo Log則對應於文件 db.redo

redo log的原理用到了“Double Write”。關於“Double Write”可參考

簡要記錄下自己的理解:因為磁盤的頁大小與操作系統的頁大小不一樣,磁盤的頁大小一般是16KB,而OS的頁大小是4KB。而數據寫入磁盤是以磁盤頁大小為單位進行的,即一次寫一個磁盤頁大小,這就需要4個OS的頁大小(4*4=16)。如果在寫入過程中出現故障(突然斷電)就會導致只寫入了一部分數據(partial page write)

而采用了“Double Write”之后,將數據寫入磁盤時,先寫到一個Recovery Buffer中,然后再寫到真正的目的文件中。在ActiveMQ的源碼PageFile.java中有相應的實現。

 

擴展知識:Linux中的日志文件系統:因為Linux的 ext文件系統采用索引節點來存儲文件的元數據,每次數據寫入磁盤之后,需要更新索引節點表。而寫入磁盤與更新索引節點表並不是“原子操作”,比如,在數據寫入磁盤后,系統發生故障,之前寫入的數據就再也找不到了。

因此,日志文件系統給Linux系統增加了一層安全性:數據寫入存儲設備之前,先將數據(或者只將索引節點信息寫日志)寫入到臨時文件中,該臨時文件稱日志。如果在數據寫入時發生故障,還可以通過日志來進行一定的恢復。

 

四,參考文檔

activeMQ 的kahadb存儲引擎分析

【ActiveMQ Tuning】KahaDB Optimization

KahaDB Overview


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM