一、MQ结构和高可用
一、MQ如何集群化部署来支撑高并发访问
RocketMq号称是可以抗住10万+并发访问。
假设此时有10万QPS+千万条消息的访问进来,如果单机的mq来抗,此时其压力是非常大的。
而如果我们利用了集群的方式部署,此时就能将10万的并发分散到各个机器上(例如10个),此时每个机器1万并发抗住搓搓有余。除了请求外,此时每个机器节点还要存储百万条数据到磁盘中(rocketmq是分布式存储,分散到各个节点存储,每个节点又有主从保证数据不丢失)。
二、MQ的基本组成
在rocketmq中,为了保证数据不丢失,此时每个节点会有master broker和slave broker(broker后面会讲,你这里先将它认为是mq)
单个MQ的简单结构:
集群后的结构:
其中你可以将NameServer理解成我们微服务中的注册中心,broker通过TCP长连接向NameServer发送注册信息(还有一些数据信息)并不断发送心跳(30秒)告诉NameServer自己还活着。然后生产者和消费者都去NameServer中拉取有关broker的所有信息,然后根据各种算法策略将消息发送到某个broker或者从某个broker中获取消息。
而broker中包含各种Topic(Topic又包含多个MessageQueue)并且有获取和持久化消息等功能。
而NameServer和broker为了保证高可用,此时NameServer进行了集群部署(各个NameServer都是平等且拥有一样相同的broker信息的,没有主从的关系),broker部署多个节点,每个节点存储一部分的消息,为了保证每个节点数据不丢失,在对每个节点进行了主从配置,其中master提供写读、slave在一定情况下提供读。(对于选举、数据同步的方面后面说明)
在broker种存在不同的Topic(可以看成一个消息集),Topic中又存在多个MessageQueue(消息队列),由于RocketMq是分布式存储的,所以此时例如OrderTopic存在两个Broker节点中,那么每个节点只会存在这个Topic的部分数据,即每个节点只有这个Topic下的部分队列(假设OrderTopic有四个MessageQueue,此时可能两个在Broker1,两个在Broker2。注意这是不固定的,这是根据一定算法来分配的)
此时生产者可以绑定某个Topic下的某个MessageQueue并向其中发送消息,消费者通过某个Topic的某个MessageQueue来拉取消息进行消费。(这些Topic、Message的信息都是Broker向NameServer注册的,生产者和消费者向NameServer拉取信息即可)(这里提个疑问,要是生产者或消费者拉取完信息后RocketMq的内部发生变化导致NameServer的信息发生更新,此时生产者得到的信息和NameServer里的信息存在误差,那此时会发生什么问题??)
二、为什么这么设计
上面对于RocketMq的基本结构和组成做了一个简单的介绍,现在分析为什么这么设计,各个部分的详细设计思路。
一、NameServer
我们都知道要部署RocketMQ,就得先部署NameServer,NameServer是支持部署多台集群的,这样可以保证高可用。且所有的broker(包括master+slave)都会将各自的信息(Broker+Topic+MessageQueue信息)注册到所有NameServer中,所以各个NameServer的信息都是相同的。
此时生产者或者消费组就会每隔一段时间定时取NameServer拉取最新的集群Broker信息(也可称为路由信息)。然后再根据一定的算法挑选一个Broker去发送或者获取消息。
此时要是Broker挂了怎么办?此时Broker和NameServer之间有一个心跳机制,Broker会每隔30秒给所有NameServer发送心跳告诉每个NameServer自己还活着。然后NameServer每手动一个Broker的心跳就去更新一下它最近一次心跳的时间。然后NameServer每10s会运行一个任务,去检查一下各个Broker的最近一次心跳时间,如果某个Broker超过120s都没心跳了,那么则认为这个Broker已经挂掉了。此时就会清除相应的记录。
那此时要是生产者更新完后知道broker有10个,而再下次更新前有一个broker挂了,此时MQ集群中只有9个broker。要是此时生产者将这个消息发送到这个宕机的broker那会发送什么?
首先,发送到挂了的broker的消息是不会成功的,此时可以有两种方法解决:一是改发到其他broker,二是可以等slave机器替换为master后再发送。(那Rocketmq用的哪一种???)二、Broker
master如何将数据同步给slave的?此时采用的模式是slave不断地去master中拉取数据(Pull模式)。
msater和slave实现读写分离了?答案是不一定,写时一定是在master,而读可以在master上,有一些情况下也可以去slave中获取。消费者去master拉取数据时,master会根据本身地负载情况和slave的同步情况,向消费组建议下一次拉取消息是从master还是slave。
master挂了怎么办?4.5版本之前rocketmq是不支持自动切换主从的(需手动),4.5之后结合Dledger的raft协议进行选举同步等才支持自动切换。(后面的部署也是基于Dledger来设计的)
broker主从同步有没有数据不一致的问题?主从不一致当然会有问题。比如master broker宕机了,那么消息就丢失了;还有就是,高并发情况下,从库落下主库太多消息的话,没法分担主库的读请求。有办法保证主从强一致,就是调整配置,在往master发送消息之后,不能立刻返回成功状态给生产者系统,而是要等消息也从master同步到了slave之后(半数slave ok即可),再返回成功状态给生产者系统。这样做的缺点就是,mq的消息吞吐性能下降。
关于rocketmq的数据同步分为2中模式,一种为异步复制,一种为同步复制,当为异步复制模式时,只要成功写入master,则会相应生成者success,同时会与slave慢慢同步数据,这种的优点的是低延迟,高吞吐,但是此模式可用性降低(如果此时master宕机,而数据没有完全同步到slave)。如果同步复制,此时要求成功写master后,同时还要求slave也成功写入,然后slave应答master ok后(半数slave ok即可),master才会应答生产者success,这种模式可用性增加,但是延迟增加,吞吐率下降。具体选择哪种模式 还是需要根据应用场景决定。【另外需要注意是 除了同步/异步复制还有,同步/异步刷盘:被写入了内存的PAGECACHE然后统一写入磁盘,还是进入内存的PAGECACHE后,立刻通知刷盘线程刷盘,完成入盘操作后返回】
三、部署一个高可用RocketMq集群
使用Dledger技术来实现主从的自动切换,而Dledger技术要求至少是一个master带两个slave。
这样三个broker组成一个group。
我们大概就是要做成这样的一个集群(slave注册图中没画出来)
注意下面的所有配置都是依照专栏来的,我可没那么多服务器来布置这么个集群:
此时分配机器如下:1、首先安装JDK环境。
2、在一台机器上构建Dledger
接着构建RocketMq
安装完后就是测试了。测试代码可以自己去网上找找。
四、监控这个MQ集群
搭建完集群后,不是说我就直接去压测,而是需要先对MQ进行JVM参数、OS参数等的配置,让MQ集群能够尽可能地使用机器硬件资源的情况下压测看出MQ集群的抗压能力。在压测的时候要观察QPS、CPU、IO、磁盘、网络负载等情况,然后看看这个MQ的瓶颈是在哪里?
(例如此时我压测过程中CPU到100%,其他的内存什么的都还剩多少,那此时就是CPU遇到瓶颈不够用了)。那次是要用什么监控工具来看这个MQ集群的各项数据?
RocketMQ提供了一个控制台让我们直观的可以观察各项数据。
进去后可以看到:
对于一些CPU、IO、磁盘、网络负载等情况则可以用Zabbix、Open——Falcon等来观察。
也可以用一些命令查看等等。
五、调整配置MQ集群的一些参数
这个部分非常重要,如果不进行调整可能你现在的机器配置很高,而这个MQ集群由于参数配置不当,导致机器资源都用不到或者用不充分。
由于RocketMq是java开发的,所以还要适当的调整jvm参数。
还要就是别往了MQ本身的一些核心参数的配置。
对于这个中间件来说,往往需要对OS内核参数、JVM参数、自身核心参数都做出相应合理的调整,然后再进行压测和上线。
一、OS内核参数
二、JVM参数配置
三、RocketMQ的核心参数
六、压测这个MQ集群
至此我们的MQ集群就搭建好了
那么此时进行压测是直接疯狂的压测,然后拿到最大限制的TPS值?
其实这个值只是这个MQ集群在这些机器下的极限值而已,而我们在真实的场景下,是要往下降一降的。例如我现在测出极限值是10万,此时观察cpu负载是100%,其他的几个指标还可以接收,那么我们在真实场景下8万TPS就是一个比较适合的值。而且我们在压测1过程中,不能只关注TPS值,而是要结合CPU、IO、磁盘、网络负载等指标进行分析。
下面我们根据观察这些指标进行压测这个集群
下面你可以去问问你们公司同事进行压测时
他们对MQ集群做过压测吗?
使用什么样的机器配置做的压测?
使用多大规模的集群做的压测?如何压测的?
在压测的过程中发现单Broker的TPS最高有多少?
在压测过程中,cpu负载、内存使用率、jvm gc频率、磁盘io负载、网卡流量负载,这些值都是如何变化的?
在压测过后,是如何规划生产集群的?
目前公司线上MQ集群的TPS多高?机器资源的负载情况如何?能否抗住?