和前面我們說的持久,事物,簽收不同的,前面的都是局限在同一台機器上,如果本機器壞了,那全部的消息也都丟失了
和Redis的持久化其實是一個概念,當我的主機宕機了也能將消息持久到硬盤或者其他上面(物理備份),方便恢復
官網詳情:http://activemq.apache.org/persistence
ActiveMQ的消息持久化機制:
JDBC,AMQ,KahaDB,LevelDB,幾種的存儲邏輯都是一致的,將消息發出后,消息中心首先將消息存儲到本地數據文件,內存數據庫或者遠程數據庫,再試圖將消息發送給接收者,成功則將消息從存儲中刪除,失敗則繼續嘗試發送
消息中心啟動后首先要檢查指定的存儲位置,若發現沒有成功發送的消息,則需要把消息發送出去
AMQ:
AMQ是一種以文件形式存儲的機制,現在淘汰了,是5.3以前的
KahaDB:
以日志形式記錄消息,5.4以后默認就是KahaDB
配置文件activemq.xml里默認KahaDB
官網詳情:http://activemq.apache.org/persistence.html
kahaDB存儲在data目錄
kahadb目錄:
KahaDB消息存儲使用一個事物日志(db.log)和一個索引文件(db.data)來存儲它的所有地址,日志相當於書的文章,索引相當於目錄
db-<number>.log用來存儲消息,當此文件存儲滿了,又會產生一個新的文件,如第一個是db-1.log,當存儲滿了,又會產生一個db-2.log,類推,當不再有引用到數據庫文件中的任何消息時,文件會被刪除或者歸檔
db.data包含了持久化的BTree索引,索引了消息數據記錄中的消息,它是消息的索引文件,本質時B樹
db.rebo:用來進行消息恢復,如果KahaDB消息存儲在強制退出后啟動,用於恢復B樹索引
lock:文件鎖,就像mysql中的悲觀鎖,表示獲得當前KahaDB讀寫操作的broker
LevelDB:
基於文件的存儲,沒有使用B樹作為索引(了解),5.8后才出現
<persistenceAdapter> <levelDB directory="activemq-data"/> </persistenceAdapter>
JDBC消息存儲:
同步消息到mysql
步驟:1.添加mysql驅動包到/activemq/lib下
2.jdbcPersistenceAdapter
配置,將其取代KahaDB
<persistenceAdapter> <jdbcPersistenceAdapter dataSource="#my-ds"/> </persistenceAdapter>
3.數據庫連接池配置
<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://自己數據庫/activemq?relaxAutoCommit=true"/> <property name="username" value="用戶名"/> <property name="password" value="密碼"/> <property name="poolPreparedStatements" value="true"/> </bean>
注:上面使用的時dbcp2連接池,所以不用引入其他jar包,因為時默認的,如果c3p0,或在druid等連接池,需要引入除了mysql驅動以外的jar包到lib下
4.建數據庫和表
數據庫名這里為activemq,如果配置沒錯,數據庫連通的話,運行代碼就會產生3張表,
ACTIVEMQ_MEGS
ACTIVEMQ_ACKS
ACTIVEMQ_LOCK
自動生成表是因為createTablesOnStartup設置為true,默認為true,
5.代碼驗證
當DeliveryMode設置為NON_PERSISTANCE時,消息被保存到內存中
設置為PERSISTANCE,消息保存到相應的文件或者數據庫中
在隊列模式中,消息一旦被消費后就從相應的文件或者數據庫刪除
在springboot工程中我投放了五條消息
上述是隊列模式的持久化
此時消息還沒有被消費掉,所以持久化到了數據庫
然后啟動消費者消費消息
此時消息被消費后,就從數據庫中刪除,為空
以上是隊列模式的持久化
官方推薦使用下面這個.效率高
<persistenceFactory> <journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="${basedir}/target" /> <!-- To use a different dataSource, use the following syntax : --> <!-- <journalPersistenceAdapterFactory journalLogFiles="5" dataDirectory="${basedir}/activemq-data" dataSource="#mysql-ds"/> --> </persistenceFactory>