2016年4月1日星期五

ActiveMQ_026:KahaDB 原理

1. KahaDB 存储
KahaDB 是一个内嵌的、事务型的消息存储方式,快速而可靠。
消息以数据日志文件的形式保存在磁盘上,当一个数据日志中的所有的消息都被消费了的时候,该数据日志文件将被标记 deletable。
在下一次清理行动中,该数据日志文件将被删除或者归档。
KahaDB 支持多个 slave,支持动态增加 slave。
KahaDB 支持使用 ZooKeeper 选举 Leader。

2. KahaDB 架构
KahaDB 的架构是按照可以满足高性能的消息读取而设计的,数据日志文件按照大小滚动,消息是以 append 方式追加到文件结尾处,所以写的速度很快。为了快速的获取消息,使用了一个 B-tree index,其中包含了所有消息的指针。完整的 B-tree index 存储在磁盘上,根据情况,部分或全部的 B-tree index 会加载到内存中。
数据日志文件包含所有持久化后的消息以及命令(比如事务边界、消息删除等等),每个数据日志文件大小是固定的,到达最大值后,会自动生成一个新的数据日志文件。日志文件中的所有消息的状态将被跟踪,当所有的消息都被消费后,该数据日志文件将被删除或者归档。
缓存中临时保存了活跃消费者将要消费的消息,如果活跃消费者存在,消息将会直接派发给与消费者关联的队列,同时也准备把消息写入数据日志文件。如果消费者承认收到消息的速度足够快,消息甚至没有写入数据日志文件。
B-tree index 为 Queue 和 Durable Topic 保持了先进先出的数据结构。
redo log 只有在 Broker 非正常停止时才会使用,用来保证 B-tree index 的完整性。

当 Broker 正常停止时, KahaDB 会将所有的缓存数据刷到文件系统中。主要包括:
(1)所有未处理的消息数据
(2)所有缓存的 Metadata 数据
并且保证 Metadata Store 中的数据与 Data Logs 中的数据一致性。

当 Broker 异常终止时,由于 Metadata Cache 中的索引信息是周期性地更新到 Metadat Store 中的,可能 Data Logs 中的某些数据在 Metadata Store 中没有对应的索引。
KahaDB 在恢复时会首先读取 Metadata Store 中的数据,然后再读取 Data Logs 中有但是在 Metadata Store 中不存在的数据,然后再根据这些数据重新在 Metadata Store 中建立索引信息。
当 Broker 异常终止时,KahaDB 会在更新 Metadata Store 之前,保存更新操作的概要信息到重做日志(db.redo)中。因为重做日志非常小,所以能在 Broker 异常终止时快速写入。当系统恢复时会判断重做日志中的信息是否需要更新到 Metadata Store 中。

如果 Metadata Store 中的数据被不可挽回的损坏了,可以删除 Metadata Store文件(db.data)来强制恢复。不过这个时候,Broker 会读取所有的 Data Logs 文件来重建 Metadata Store,需要一段比较长的时间。

KahaDB 可以检测是否有数据日志文件丢失,如果有丢失,默认将会抛出一个异常然后关闭。便于管理员调查丢失的数据日志文件,并手动还原。
可以通过设置 ignoreMissingJournalfiles=true,让 Broker 在启动时忽略这些丢失的数据日志文件。
可以通过设置 checkForCorruptJournalFiles=true,让 Broker 在启动时检测数据日志文件的完整性。

3. KahaDB 目录结构


3.1 db-*.log
用来存放完整的每条消息(包括事务、目的地、id、优先级、具体内容等)和producerSequenceIdTracker (用来验证每个消息生成者发送的消息是否重复的数据结构)。它随着消息数量的增多,默认每 32M 一个文件(可以修改默认大小),文件名按照数字进行编号,如db-1.log、db-2.log、db-3.log。
当一条消息的大小超过数据日志文件大小时,要修改数据文件大小。



3.2 db.data
包含多个 B-tree index 实例,作用分别如下:
(1)Metadata 类的 destinations
用来保存该 Broker上有哪些 Queue 或 Topic。
(2)StoredDestination 类的 orderIndex 属性中的 defaultPriorityIndex、lowPriorityIndex、highPriorityIndex
这三个属性是为消息优先级排序而设计的,它们的主要作用是为 AbstractStoreCursor 类的 doFillBatch 方法服务的,也就是常说的消息指针(message cursors)。当消息指针需要从磁盘文件中装载一批消息的时候会使用这三个属性。
(3)StoredDestination 类的 locationIndex
该btree的主要作用包括:
系统重启进行恢复操作的时候,要移除掉不在db-*.log文件里的消息;
在系统进行定时checkpointUpdate时使用
(4)StoredDestination类的messageIdIndex
主要作用是消息确认 acknowledge 操作时,通过消息ID在 messageIdIndex 中删除对应的记录,并依据返回的值删除orderIndex和locationIndex中的记录。


3.3 db.redo
主要作用是 “Double Write”,具体代码参看 PageFile类的 writeBatch 方法。它的原理可参考(http://www.mysqlperformanceblog.com/2006/08/04/innodb-double-write/)
 


3.4 db.free
当前 db.data 文件里哪些页面是空闲的,文件具体内容是所有空闲页的ID。

4. KahaDB 属性说明
(1)directory 保存 Message Store 数据文件的目录,默认值:activemq-data。
(2)indexWriteBatchSize 批量更新索引的阀值,当要更新的索引到达这个索引时,批量更新到 Metadata Store中,默认值:1000。
(3)indexCacheSize    指定metadata cache的大小,默认值:10000。
(4)enableIndexWriteAsync 写入索引文件到 Metadata Store 中的方式是否采用异步写入,默认值:false。
(5)journalMaxFileLength    消息持久数据文件的大小,默认值:32M。
(6)enableJournalDiskSyncs    如果为true,保证使用同步写入的方式持久化消息到数据日志文件中,默认值:true。
(7)cleanupInterval 清除(清除或归档)不再使用的数据日志文件的时间周期(毫秒),默认值:30000。
(8)checkpointInterval    写入索引信息到 Metadata Store 中的时间周期(毫秒),默认值:5000。
(9)ignoreMissingJournalfiles 是否忽略丢失的数据日志文件。如果为 false,当丢失了数据日志文件时,Broker 启动时会抛异常并关闭,默认值:false。
(10)checkForCorruptJournalFiles    如果为 true,Broker 在启动的时候会检测数据日志文件是否损坏,若损坏便尝试恢复它,默认值:false。
(11)checksumJournalFiles 如果为true,KahaDB 为数据日志文件产生一个 checksum,以便能够检测数据日志文件是否损坏,默认值:false。
(12)archiveDataLogs    如果为 true,当达到 cleanupInterval 周期时,会归档数据日志文件而不是删除,默认值:false。
(13)directoryArchive 指定归档数据日志文件存放的路径,默认值:null。
(14)databaseLockedWaitDelay    在使用主从数据库备份时,等待获取数据库上的锁的延迟时间,默认值:10000。
(15)maxAsyncJobs 等待写入数据日志文件的任务队列的最大数量,应该大于或等于最大并发 producer 的数量,配合并行存储转发属性使用,默认值:10000。
(16)concurrentStoreAndDispatchTransactions    如果为 true,转发消息的时候同时提交事务,默认值:false。
(17)concurrentStoreAndDispatchTopics    如果为 true,转发 Topic 消息的时候同时存储消息的 Message Store 中,默认值:false。
(18)concurrentStoreAndDispatchQueues    如果为 true,转发 Queue 消息的时候同时存储消息到 Message Store 中,默认值:true。

注意,以上这些 KahaDB 这些特性并不能100%保证 Broker 异常终止时不造成消息丢失。如果需要保证系统的高可靠性,建议部署到容灾系统上,例如 RAID 磁盘阵列中。

参考文献:
1. http://netcomm.iteye.com/blog/1455086
2. http://berdy.iteye.com/blog/813300
3. http://activemq.apache.org/kahadb.html
4. http://activemq.apache.org/kahadb-master-slave.html

没有评论: