ActiveMQ消息持久化
什么是消息持久化
在发送者将消息发送出去后,消息中心首先将消息存储到本地数据文件、内存数据库或者远程数据库等,然后试图将消息发送给接收者,发送成功则将消息从存储中删除,失败则继续尝试。
消息中心启动以后首先要检查制定的存储位置,如果有未发送成功的消息,则需要把消息发送出去。
ActiveMQ持久化方式
AMQ、KahaDB、JDBC、LevelDB。
AMQ
AMQ是一种文件存储形式,它具有写入速度快和容易恢复的特点。消息存储在一个个文件中,文件的默认大小为32M,如果一条消息的大小超过了32M,那么这个值必须设置大一点。当一个存储文件中的消息已经全部被消费,那么这个文件将被标识为可删除,在下一个清除阶段,这个文件被删除。AMQ适用于ActiveMQ5.3之前的版本。
KahaDB
KahaDB是基于文件的本地数据库储存形式,虽然没有AMQ的速度快,但是它具有强扩展性,恢复的时间比AMQ短,从5.4版本之后KahaDB做为默认的持久化方式。
KahaDB是一种可嵌入式的事务性的持久化机制
KahaDB,主要特性有:
1、日志形式存储消息。
2、消息索引以B-Tree结构存储,可以快速更新
3、完全支持JMS事务
4、支持多种恢复机制
上图展示的是KahaDB的结构图。消息存储在基于文件的数据日志中。如果消息发送成功,变标记为可删除的。
系统会周期性的清除或者归档日志文件。
消息文件的位置索引存储在内存中,这样能快速定位到。定期将内存中的消息索引保存到metadata store中,避免大量消息未发送时,消息索引占用过多内存空间。
Data logs
数据日志中保存着消息以及目的地、订阅、事务等相关信息。这些信息在日志文件中并未按照一个特定的格式来保存,所以就需要索引各类信息,以便能快速定位到。
Metadata cache
在内存中保存日志文件中各类信息的索引,索引信息包含一个MessageId与消息在日志文件中的偏移量的对应关系。
所有索引以B-Tree结构存在内存中,便于在一个有序的list上快速的查找,插入以及删除。内存中的消息索引会定期的保存到Metadata store中。具体时间周期可以设置checkpointInterval属性。理想情况下Metadata cache越大愈好,这样在定位消息的时候就不尽量少的去Metadata store中获取索引了。实际可以参考db.data文件的大小来设置。indexCacheSize 便是设置缓存的大小。
Metadata store
在db.data文件中保存消息日志中消息的元数据,也是以B-Tree结构存储的,定时从Metadata cache更新数据。同时,Metadata store中也会备份一些在消息日志中存在的信息,这样可以让Broker实例快速启动。即便metadata store文件被破坏或者误删除了。broker可以读取Data logs恢复过来,只是速度会相对较慢些。
Metadata cache与Metadata store同步
KahaDB提供了两种触发同步设置
1、设定一个阀值,当Metadata cache与Metadata store中的索引不同的数量达到这个阀值时,触发同步。indexWriteBatchSize
便是设置这个阀值。
2、设置一个时间周期,当时间周期到了后,不管Metadata cache与Metadata store是否不同,都触发同步。
通过checkpointInterval设置一个时间周期。
通常为了达到更高的性能,会将indexWriteBatchSize值设置很大。只在到达checkpointInterval时间点时才同步。这样做的风险就是有可能在系统意外down机时丢失部分metadata信息。
JDBC
可以将消息存储到数据库中,例如:Mysql、SQL Server、Oracle、DB2。
dataSource指定持久化数据库的bean,createTablesOnStartup是否在启动的时候创建数据表,默认值是true,这样每次启动都会去创建数据表了,一般是第一次启动的时候设置为true,之后改成false。
LevelDB
这种文件系统是从ActiveMQ5.8之后引进的,它和KahaDB非常相似,也是基于文件的本地数据库储存形式,但是它提供比KahaDB更快的持久性。
与KahaDB不同的是,它不是使用传统的B-树来实现对日志数据的提前写,而是使用基于索引的LevelDB。
与Kafka持久化对比
Kafka的存储布局非常简单。话题的每个分区对应一个逻辑日志。物理上,一个日志为相同大小的一组分段文件。每次生产者发布消息到一个分区,代理就将消息追加到最后一个段文件中。当发布的消息数量达到设定值或者经过一定的时间后,段文件真正写入磁盘中。写入完成后,消息公开给消费者。
与传统的消息系统不同,Kafka系统中存储的消息没有明确的消息Id。
消息通过日志中的逻辑偏移量(只存储位置信息)来公开。这样就避免了维护配套密集寻址,用于映射消息ID到实际消息地址的随机存取索引结构的开销。消息ID是增量的,但不连续。要计算下一消息的ID,可以在其逻辑偏移的基础上加上当前消息的长度。
消费者始终从特定分区顺序地获取消息,如果消费者知道特定消息的偏移量,也就说明消费者已经消费了之前的所有消息。消费者向代理发出异步拉请求,准备字节缓冲区用于消费。每个异步拉请求都包含要消费的消息偏移量。Kafka利用sendfile API高效地从代理的日志段文件中分发字节给消费者。

浙公网安备 33010602011771号