1 .如何解决io问题?

JMQ使用的是Netty4.0,而不是由AMQ自行开发并通过重复车轮来解决IO问题。 该框架开源,支持epoll,编程模型相对简单。 这在一定程度上减少了服务器端的开发工作,也降低了服务器端的复杂性。

在APP应用层,我们定制了JMQ协议,并完全自行开发了序列化和反序列化。 这种序列化反序列化方案会在一定程度上降低开发效率,但无需考虑采用第三方序列化和反序列化方案会导致性能下降的问题,显然会提高性能。

2 .如何保存消息

JMQ存储分为日志文件(journal )、消息队列文件(queue )和消耗位置文件(offset ),它们都存储在Broker所在计算机的本地磁盘上。

日志文件,主要保存消息内容。 包括消息所在的队列文件的位置在内,具有以下特征。

a .同一broker上不同的主题消息存储在同一日志文件中,日志文件由固定大小分隔;

b .文件名起始全局偏移

c .添加消息顺序。

d .日志文件同步刷

由于JMQ主要用于对可靠性要求非常高的订单、支付等,因此broker必须保证接收到的所有消息落入物理磁盘。 这样的日志文件主要是为了提高多topic大并发磁盘的写入性能而设计的。 不仅是模型的设计,为了提高写入性能,从逻辑上实现了Group commit。 下图是JMQ的组提交的基本图像。

图5 :组提交映像

消息队列。 主要是保存消息的日志文件的全局偏移。 此文件具有以下特征:

a .同一broker上不同主题的队列信息存储在不同的队列文件中,队列文件由固定大小分隔;

b .文件名为全局偏移

c .添加索引顺序;

d .队列文件的异步刷。

写入日志是单线程的,因此可以在写入之前预先获取队列文件中的消息位置,然后将该位置写入日志文件。 因此,如果日志文件写入成功,即使队列文件写入失败,队列文件也可以从日志文件中恢复队列,因此队列文件使用异步刷子。

图6 :日志文件和队列文件模型

消费场所文件:

消耗位置文件主要用于存储不同读者对topic消耗的队列的偏移。

下图简要说明了消息在服务器端的流程。

图7 :消息流示意图

3 .如何进行灾后恢复?

关于灾难恢复,上一节提到了所有消息都将在broker上落地,但这还不够。 必须确保即使在独立故障或机房故障的情况下,数据也能恢复。 因此,数据灾难恢复需要一个完整的计划。 AMQ采用的方案是,主机和从机分布在一个数据中心中,主机和从机同步进行复制。

JMQ采用主从同步复制、至少一个备份、主从相同的数据中心、备份不同的数据中心、主从同步复制和备份异步复制等方法应对数据灾难主从同步复制可确保同一消息至少有两个完整备份。 如果一个备份丢失,另一个备份仍然可用。 备份节点可以确保即使整个数据中心停止运行,也能恢复大多数消息

图8:JMQ复制模型

4.Push or pull? 消息是如何路由的?

JMQ采用拉动模式。 这意味着,在消息从producer发送到broker后,consumer会自行发出请求并去broker拿消息。

发件人的路由与AMQ客户端采取的策略基本相同。

消费者路由选择几乎和AMQ一样是随机的,不同之处在于JMQ为拉模式,在Broker上采取长轮询策略。

5 .如何处理消费失败的新闻?

与AMQ不同,JMQ的broker支持直接重试,因此Consumer在处理消息失败时直接向服务器发送重试消息命令,服务器在收到命令后再签入该消息。 然后,当consumer启动提取消息的命令时,服务器根据一定的策略从数据库中取出消息,然后返回consumer进行处理。 这样,JMQ客户端就可以减少对第三方服务的依赖。

6 .如何记录消息轨道?

JMQ消息轨道功能的整体流程与AMQ基本相同,但主要的不同在于,JMQ将有关消息轨道的信息保存在HBase中,从而JMQ消息轨道信息的保存周期变长,可保存的量也变多,通过各种手段最大限度地减少

7 .如何管理元数据?

在第一部分中,我们知道AMQ的元数据将持久化在MySQL中,在签入的同时写入ZooKeeper,并从ZK分发给Broker和客户端。 这有两个问题

答:客户端引入了名为ZooKeeper的第三方服务,服务越引入该客户端的稳定性和可维护性越差。

b .由于注册中心(即ZooKeeper )直接暴露在客户端上,注册中心的连接数增加,出现故障时保护注册中心所需的手段不足。

在JMQ中依然利用MySQL使元数永久化

据,同时也会将元数据写入ZooKeeper,ZooKeeper再通知到Broker,但客户端不再直接连接ZooKeeper,而是转而连接Broker,从Broker上获取元数据信息。由于每个Broker都有全量的元数据信息,所以客户端端连接任意的Broker都能获取到元数据信息。这种设计就带来了几个好处:

a.减少了客户端对ZooKeeper服务的依赖,至此我们客户端就只需和broker通信,客户逻辑得到了简化,客户端稳定得到了极大提升。

b.ZooKeeper不再暴露给客户端,这样ZooKeeper的稳定性也有了保证。

c.由于连接任意一个Broker都能获取到元数据,极端情况下即便有个别broker宕机也不影响客户端获取元数据,所以从另外一个角度来看这又提高了我们注册中心的可用性。

8.其他。

除了以上提到的一些基本问题之外,我们还解决了很多问题,由于篇幅问题就

不一一在此罗列说明,其中包括但不限于:

a. 如何实现严格顺序消息;

b. 如何实现广播消息;

c. 如何实现两阶段事务;

d. 如何实现消息回放。

下面是JMQ的一个粗略整体架构图:

图9:JMQ架构图

JMQ性能数据

测试所用机器情况:

场景1:一主一从,Master同步刷盘+同步复制到Slave

场景2:一主一从,Master异步刷盘+异步复制Slave

JMQ规模

Topic数量:1000+

接入应用数量:2500+

单日消息入队数量:500亿+