Apache ActiveMQ Artemis 提供了兩種持久化選項。檔案日誌針對訊息傳遞使用案例進行了高度優化,並提供了卓越的效能;還有 JDBC 儲存,它使用 JDBC 連接到您選擇的資料庫。
1. 檔案日誌 (預設)
檔案日誌是一個僅附加的日誌。它由磁碟上的一組檔案組成。每個檔案都被預先建立為固定大小,並最初填充了填充內容。當在伺服器上執行操作時,例如新增訊息、更新訊息、刪除訊息,記錄會附加到日誌中。當一個日誌檔案已滿時,我們會移動到下一個檔案。
由於記錄僅被附加,即添加到日誌的末尾,因此我們最大程度地減少了磁頭移動,也就是說,我們最大程度地減少了隨機存取操作,這通常是磁碟上最慢的操作。
使檔案大小可配置意味著可以選擇最佳大小,也就是說,使每個檔案都適合在磁碟柱面上。現代磁碟拓撲很複雜,我們無法控制檔案映射到哪個柱面,因此這不是一門精確的科學。但是,通過最小化檔案使用的磁碟柱面數量,我們可以最小化磁頭移動的量,因為只需旋轉磁碟即可存取整個磁碟柱面 - 磁頭不必移動。
由於刪除記錄被添加到日誌中,Apache ActiveMQ Artemis 具有一個複雜的檔案垃圾回收演算法,可以確定是否需要特定的日誌檔案 - 即,其所有資料是否已在相同或其他檔案中刪除。如果是這樣,則可以回收該檔案並重複使用。
Apache ActiveMQ Artemis 還具有一個壓縮演算法,該演算法會從日誌中刪除死空間並壓縮資料,使其在磁碟上佔用的檔案更少。
如果需要,該日誌還完全支援交易操作,同時支援本地交易和 XA 交易。
該日誌的大部分是用 Java 編寫的,但是我們將與實際檔案系統的互動抽象出來,以允許不同的可插拔實現。Apache ActiveMQ Artemis 提供了兩種實現
1.1. 日誌和資料保留
ActiveMQ Artemis 提供了一種儲存和重播歷史資料的方法。有關更多資訊,請參閱資料保留章節。
1.3. Linux 非同步 IO
第二種實現使用一個輕量級的原生程式碼封裝器來與 Linux 非同步 IO 函式庫 (AIO) 通訊。使用 AIO,當資料到達磁碟時,Apache ActiveMQ Artemis 將被回呼,從而使我們能夠完全避免顯式同步,並且當 AIO 通知我們資料已持久化時,只需發回完成確認即可。
使用 AIO 通常會比使用 Java NIO 提供更好的效能。
只有在運行 Linux 2.6 或更高版本的核心,並且安裝了 libaio(如果尚未安裝)後,才能使用此日誌選項。有關如何安裝 libaio 的說明,請參閱安裝 AIO 章節。
另外,請注意 AIO 僅適用於以下檔案系統:ext2、ext3、ext4、jfs、xfs 和 NFSV4。
有關 libaio 的更多資訊,請參閱lib AIO。
libaio 是核心專案的一部分。
1.4. 記憶體映射
第三種實現使用檔案支援的 READ_WRITE 記憶體映射,針對 OS 頁面快取與檔案系統介接。
這提供了極佳的效能(尤其是在嚴格的程序失敗持久性要求下)、幾乎為零的複製(實際上是核心頁面快取)和零垃圾回收(從 Java HEAP 的角度來看)操作,並且可在任何具有 Java 4+ 執行階段的平台上運行。
在斷電持久性要求下,它的效能至少與 NIO 日誌相當,唯一的例外是核心版本小於或等於 2.6 的 Linux OS,在這種情況下,用於確保耐用寫入的 msync 實作與 NIO 日誌使用的 fsync 不同(並且速度較慢)。
它受益於 OS 巨型頁面的配置,尤其是在使用大量日誌檔案並將其大小調整為 OS 頁面大小(以位元組為單位)的倍數時。
1.5. 標準檔案
標準 Apache ActiveMQ Artemis 核心伺服器使用兩個日誌實例
-
綁定日誌。
此日誌用於儲存與綁定相關的資料。這包括部署在伺服器上的佇列及其屬性集。它還儲存諸如 ID 序列計數器之類的資料。
綁定日誌始終是一個 NIO 日誌,因為與訊息日誌相比,它的吞吐量通常很低。
此日誌上的檔案以
activemq-bindings
為前綴。每個檔案都有一個bindings
副檔名。檔案大小為1048576
,並且位於綁定資料夾中。 -
訊息日誌。
此日誌實例儲存所有與訊息相關的資料,包括訊息本身和重複 ID 快取。
預設情況下,Apache ActiveMQ Artemis 將嘗試使用 AIO 日誌。如果 AIO 不可用,例如,該平台不是具有正確核心版本的 Linux,或者尚未安裝 AIO,則它將自動回退為使用 Java NIO,Java NIO 在任何 Java 平台上都可用。
此日誌上的檔案以
activemq-data
為前綴。每個檔案都有一個amq
副檔名。檔案大小預設為10485760
(可配置),並且位於日誌資料夾中。
對於大型訊息,Apache ActiveMQ Artemis 將它們持久化到訊息日誌之外。這在大型訊息中進行了討論。
Apache ActiveMQ Artemis 也可以在記憶體不足的情況下將訊息分頁到磁碟。這在分頁中進行了討論。
如果完全不需要持久化,也可以將 Apache ActiveMQ Artemis 設定為不將任何資料持久化到儲存,如為零持久化設定代理程式章節中所述。
1.5.1. 設定綁定日誌
使用 broker.xml
中的以下屬性來設定綁定日誌
- bindings-directory
-
這是綁定日誌所在的目錄。預設值為
data/bindings
。 - create-bindings-dir
-
如果將此設定為
true
,則如果bindings-directory
中指定的位置尚不存在,則會自動建立該位置的綁定目錄。預設值為true
1.5.2. 設定 jms 日誌
jms 配置與綁定日誌共用其配置。
1.5.3. 設定訊息日誌
使用 broker.xml
中的以下屬性來設定訊息日誌
- journal-directory
-
這是訊息日誌所在的目錄。預設值為
data/journal
。為了獲得最佳效能,我們建議將日誌置於其自己的實體磁碟區上,以最大程度地減少磁頭移動。如果日誌位於與其他可能正在寫入其他檔案(例如,綁定日誌、資料庫或交易協調器)的程序共用的磁碟區上,則當它寫入這些檔案時,磁頭可能會在這些檔案之間快速移動,從而大幅降低效能。
當訊息日誌儲存在 SAN 上時,我們建議儲存在 SAN 上的每個日誌實例都獲得其自己的 LUN(邏輯單元)。
- node-manager-lock-directory
-
這是節點管理程式檔案鎖所在的目錄。預設情況下,具有與
journal-directory
相同的值。當訊息日誌位於 SAN 上,並且正在將其用作與同一實體機器上的代理程式實例一起使用的共用儲存 HA策略時,這非常有用。
- create-journal-dir
-
如果將此設定為
true
,則如果journal-directory
中指定的位置尚不存在,則會自動建立該位置的日誌目錄。預設值為true
- journal-type
-
有效值為
NIO
、ASYNCIO
或MAPPED
。選擇
NIO
會選擇 Java NIO 日誌。選擇ASYNCIO
會選擇 Linux 非同步 IO 日誌。如果您選擇ASYNCIO
,但您未運行 Linux 或未安裝 libaio,則 Apache ActiveMQ Artemis 會偵測到此情況,並自動回退為使用NIO
。選擇MAPPED
會選擇 Java 記憶體映射日誌。 - journal-sync-transactional
-
如果將此設定為 true,則 Apache ActiveMQ Artemis 將確保所有交易資料在交易邊界(提交、準備和回滾)時刷新到磁碟。預設值為
true
。 - journal-sync-non-transactional
-
如果將此設定為 true,則 Apache ActiveMQ Artemis 將確保每次都將非交易訊息資料(發送和確認)刷新到磁碟。此項的預設值為
true
。 - journal-file-size
-
每個日誌檔案的大小(以位元組為單位)。此項的預設值為
10485760
位元組 (10MiB)。 - journal-min-files
-
日誌將維護的最小檔案數。當 Apache ActiveMQ Artemis 啟動且沒有初始訊息資料時,Apache ActiveMQ Artemis 將預先建立
journal-min-files
個檔案。建立日誌檔案並用填充內容填充它們是一項相當昂貴的操作,我們希望在運行時盡可能減少這種情況,因為檔案會被填滿。通過預先建立檔案,當一個檔案被填滿時,日誌可以立即繼續使用下一個檔案,而無需暫停來建立它。
根據您預計佇列在穩定狀態下包含多少資料,您應該調整此檔案數以符合該資料總量。
- journal-pool-files
-
系統將建立所需的檔案數,但是在回收檔案時,它將縮減回
journal-pool-files
。此參數的預設值為 -1,這意味著它在建立後永遠不會刪除日誌上的檔案。
請注意,系統無法無限增長,因為您仍然需要為可以無限增長的目的地使用分頁。
請注意:如果您獲得過多的檔案,則可以使用壓縮。
- journal-max-io
-
寫入請求會在提交至系統執行前排入佇列。此參數控制在任何時間點 IO 佇列中可存在的最大寫入請求數。如果佇列已滿,則寫入操作會被阻塞,直到釋放出空間為止。
使用 NIO 時,此值應始終等於
1
。使用 ASYNCIO 時,預設值應為
500
。系統會根據使用 NIO 或 ASYNCIO 維護此參數的不同預設值(NIO 的預設值為 1,ASYNCIO 的預設值為 500)。
有一個限制,且 ASYNCIO 的總最大值不能高於作業系統層級設定的值 (/proc/sys/fs/aio-max-nr),通常為 65536。
- journal-buffer-timeout
-
我們並非在每次需要刷新的寫入操作時都進行刷新,而是維護一個內部緩衝區,並在緩衝區已滿或逾時(以較早者為準)時刷新整個緩衝區。這適用於 NIO 和 ASYNCIO,並允許系統在許多需要刷新的並行寫入操作下更好地擴展。
此參數控制緩衝區若尚未填滿,則會在逾時時刷新的時間。ASYNCIO 通常可以處理比 NIO 更高的刷新率,因此系統會為 NIO 和 ASYNCIO 維護不同的預設值(NIO 的預設值為 3333333 奈秒 - 每秒 300 次,ASYNCIO 的預設值為 500000 奈秒 - 即每秒 2000 次)。
將此屬性設定為 0 會停用內部緩衝區,且寫入操作會立即直接寫入日誌檔。
透過增加逾時時間,您或許能夠在犧牲延遲的情況下增加系統輸送量,預設參數的選擇旨在於輸送量和延遲之間取得合理的平衡。
- journal-buffer-size
-
ASYNCIO 上定時緩衝區的大小。預設值為
490KiB
。 - journal-compact-min-files
-
我們可以考慮壓縮日誌之前所需的最小檔案數。壓縮演算法在您至少擁有
journal-compact-min-files
檔案之前不會啟動。將此值設定為 0 將會完全停用壓縮功能。但這可能很危險,因為日誌可能會無限增長。請謹慎使用!
此參數的預設值為
10
。 - journal-compact-percentage
-
啟動壓縮的閾值。當日誌空間中被視為有效數據的比例小於此百分比時,我們就會開始壓縮。另請注意,在您的日誌中至少有
journal-compact-min-files
個數據檔案之前,壓縮不會啟動。此參數的預設值為
30
。 - journal-lock-acquisition-timeout
-
在放棄之前,等待取得日誌檔案鎖定的時間(以毫秒為單位)。
此參數的預設值為
-1
(即無限期)。 - journal-datasync
-
這將停用在日誌寫入時使用 fdatasync。啟用時,它確保完全的電源故障耐用性,否則確保日誌寫入的程序故障耐用性(作業系統保證)。這對於依賴 *fsync*/ *msync* 強制將寫入變更至磁碟的
NIO
和MAPPED
日誌特別有效。預設值為
true
。
1.6. 安裝 AIO
Java NIO 日誌提供了出色的效能,但如果您使用 Linux Kernel 2.6 或更高版本執行 Apache ActiveMQ Artemis,我們強烈建議您使用 ASYNCIO
日誌以獲得最佳的持久性效能。
無法在其他作業系統或較舊版本的 Linux 核心下使用 ASYNCIO 日誌。
如果您執行的是 Linux Kernel 2.6 或更高版本,而且尚未安裝 libaio
,您可以按照下列步驟輕鬆安裝它。
使用 yum(例如在 Fedora 或 Red Hat Enterprise Linux 上)
yum install libaio
使用 aptitude(例如在 Ubuntu 或 Debian 系統上)
apt-get install libaio
2. JDBC 持久性
Apache ActiveMQ Artemis JDBC 持久性層提供了使用資料庫儲存代理程式狀態(訊息、位址和佇列定義等)的能力。
使用 ActiveMQ Artemis 檔案日誌是建議的組態,因為它提供更高的效能,並且更加成熟。JDBC 對於分頁和大型訊息的效能都特別降低。JDBC 持久性層的目標對象是必須使用資料庫的使用者,例如由於公司內部政策。 |
ActiveMQ Artemis 目前支援少數資料庫廠商
-
PostgreSQL
-
MySQL
-
Microsoft SQL Server
-
Oracle
-
DB2
-
Apache Derby
JDBC 儲存會使用 JDBC 連線,以將訊息和繫結資料儲存在資料庫表格中的記錄中。儲存在資料庫表格中的資料會使用 Apache ActiveMQ Artemis 內部編碼進行編碼。
2.1. 設定 JDBC 持久性
若要設定 Apache ActiveMQ Artemis 使用資料庫來持久化訊息和繫結資料,您必須執行兩項操作。
-
請參閱關於新增執行階段相依性的文件,以瞭解如何讓 JDBC 驅動程式可供代理程式使用。
-
在 broker.xml 組態檔中的
<core>
元素下建立 store 元素。例如
<store>
<database-store>
<jdbc-driver-class-name>org.apache.derby.jdbc.EmbeddedDriver</jdbc-driver-class-name>
<jdbc-connection-url>jdbc:derby:data/derby/database-store;create=true</jdbc-connection-url>
<bindings-table-name>BINDINGS_TABLE</bindings-table-name>
<message-table-name>MESSAGE_TABLE</message-table-name>
<page-store-table-name>MESSAGE_TABLE</page-store-table-name>
<large-message-table-name>LARGE_MESSAGES_TABLE</large-message-table-name>
<node-manager-store-table-name>NODE_MANAGER_TABLE</node-manager-store-table-name>
</database-store>
</store>
- jdbc-connection-url
-
資料庫伺服器的完整 JDBC 連線 URL。連線 URL 應包含所有組態參數和資料庫名稱。
使用 XML 組態檔設定伺服器時,請務必逸出任何非法字元;例如,「&」在 JDBC 連線 URL 中很常見,應逸出為「&」。 - bindings-table-name
-
ActiveMQ Artemis 伺服器將持久化繫結資料的表格名稱。指定表格名稱允許使用者在多個伺服器之間共用單一資料庫,而不會互相干擾。
- message-table-name
-
ActiveMQ Artemis 伺服器將持久化繫結資料的表格名稱。指定表格名稱允許使用者在多個伺服器之間共用單一資料庫,而不會互相干擾。
- large-message-table-name
-
ActiveMQ Artemis 伺服器將持久化訊息和相關資料的表格名稱。指定表格名稱允許使用者在多個伺服器之間共用單一資料庫,而不會互相干擾。
- page-store-table-name
-
用於儲存分頁儲存目錄資訊的表格名稱。請注意,每個位址都會有自己的分頁表格,該表格將使用此名稱,並附加一個長達 20 個字元的唯一 ID。
- node-manager-store-table-name
-
ActiveMQ Artemis 伺服器將持久化 HA 共用儲存鎖定(即主要和備份)和 HA 相關資料的表格名稱。指定表格名稱允許使用者在多個伺服器之間共用單一資料庫,而不會互相干擾。每個共用儲存主要/備份配對都必須使用相同的表格名稱,且不支援在多個(且不相關的)主要/備份配對之間共用相同的表格。
- jdbc-driver-class-name
-
所需資料庫驅動程式的完整類別名稱。
- jdbc-network-timeout
-
JDBC 網路連線逾時時間(以毫秒為單位)。預設值為 20000 毫秒(即 20 秒)。使用共用儲存時,建議將其設定為小於或等於
jdbc-lock-expiration
。 - jdbc-lock-renew-period
-
JDBC 鎖定的保持連線服務週期(以毫秒為單位)。預設值為 2000 毫秒(即 2 秒)。
- jdbc-lock-expiration
-
JDBC 鎖定被視為有效而無需保持連線的時間(以毫秒為單位)。預設值為 20000 毫秒(即 20 秒)。
- jdbc-journal-sync-period
-
日誌與 JDBC 同步的時間(以毫秒為單位)。預設值為 5 毫秒。
- jdbc-allowed-time-diff
-
在更新和驗證主要和備份鎖定時,要求資料庫目前時間時,代理程式和資料庫之間的最大時間偏移量(以毫秒為單位)。目前,此值僅會影響記錄,如果偵測到的差異超過限制,則會顯示警告。預設值為 250 毫秒。
- jdbc-max-page-size-bytes
-
分頁可使用的最大大小。預設值和建議的最大值為 100K 位元組。使用較大的大小將會導致下載大型 Blob,這會在使用分頁訊息時影響效能。
某些 DBMS(例如 Oracle,30 個字元)對表格名稱的大小有限制,在設定 Artemis 資料庫儲存的表格名稱時應將此納入考量,特別注意分頁儲存表格名稱,該名稱可以附加一個長達 20 個字元的唯一 ID。(對於 Oracle,這表示設定分頁儲存表格名稱的最大大小為 10 個字元)。 |
如果您需要編碼,也可以明確地新增使用者和密碼,而不是在 JDBC URL 中,如下所示
<store>
<database-store>
<jdbc-driver-class-name>org.apache.derby.jdbc.EmbeddedDriver</jdbc-driver-class-name>
<jdbc-connection-url>jdbc:derby:data/derby/database-store;create=true</jdbc-connection-url>
<jdbc-user>ENC(dasfn353cewc)</jdbc-user>
<jdbc-password>ENC(ucwiurfjtew345)</jdbc-password>
<bindings-table-name>BINDINGS_TABLE</bindings-table-name>
<message-table-name>MESSAGE_TABLE</message-table-name>
<page-store-table-name>MESSAGE_TABLE</page-store-table-name>
<large-message-table-name>LARGE_MESSAGES_TABLE</large-message-table-name>
<node-manager-store-table-name>NODE_MANAGER_TABLE</node-manager-store-table-name>
<jdbc-page-max-size-bytes>100K</jdbc-page-max-size-bytes>
</database-store>
</store>
2.2. 設定 JDBC 連線集區
若要設定 Apache ActiveMQ Artemis 使用具有 JDBC 連線集區的資料庫,您需要設定資料來源屬性,例如
<store>
<database-store>
<data-source-properties>
<data-source-property key="driverClassName" value="com.mysql.jdbc.Driver" />
<data-source-property key="url" value="jdbc:mysql://127.0.0.1:3306/artemis" />
<data-source-property key="username" value="artemis" />
<data-source-property key="password" value="artemis" />
<data-source-property key="poolPreparedStatements" value="true" />
</data-source-properties>
<bindings-table-name>BINDINGS</bindings-table-name>
<message-table-name>MESSAGES</message-table-name>
<large-message-table-name>LARGE_MESSAGES</large-message-table-name>
<page-store-table-name>PAGE_STORE</page-store-table-name>
<node-manager-store-table-name>NODE_MANAGER_STORE</node-manager-store-table-name>
</database-store>
</store>
您可以在 https://commons.apache.org/proper/commons-dbcp/configuration.html 找到資料來源屬性的文件。
若要遮罩屬性的值,您可以使用與遮罩密碼相同的程序。
請注意,僅在沒有用戶端傳送訊息時,重新連線才會運作。相反地,如果嘗試在重新連線期間寫入日誌表格,則代理程式將會快速失敗並關閉。
3. 零持久性
在某些情況下,訊息系統有時需要零持久性。設定 Apache ActiveMQ Artemis 執行零持久性非常簡單。只需將 broker.xml
中的參數 persistence-enabled
設定為 false
即可。
請注意,如果您將此參數設定為 false,則將不會進行任何持久化。這表示不會持久化任何綁定資料、訊息資料、大型訊息資料、重複 ID 快取或分頁資料。