写点什么

五分钟搞懂 MySQL 主从复制原理,附带学习经验

发布于: 1 小时前

1、PTP 模型

Point-to-Point,点对点通信模型。PTP 是基于队列(Queue)的,一个队列可以有多个生产者,和多个消费者。消息服务器按照收到消息的先后顺序,将消息放到队列中。队列中的每一条消息,只能由一个消费者进行消费,消费之后就会从队列中移除。



需要注意的是,尽管这里使用 Queue 的概念,但并不是先进入队列消息,一定会被先消费。在存在多个下游 Consumer 情况下,一些消息中间件,例如 ActiveMQ,为了提升消费能力,会将队列中的消息分发到不同 Consumer 并行进行处理。这意味着消息发送的时候可能是有序的,但是在消费的时候,就变成无序了。为了保证消费的有序,一些 MQ 提供了**"专有消费者”或者"排他消费者”**的概念,在这种情况下,队列中的消息仅允许一个消费者进行消费,如果存在多个消费者,那么从中选择一个。但是,这意味着在消息在处理中没有了并行性。如果消息量很多的情况下,将会产生消息积压。为了解决"专有消费者”的性能问题,一些消息中间件采用分区的概念来解决性能问题,我们将在后文进行介绍。

2、Pub/Sub 模型

publish-and- subscribe, 即发布订阅模型。在 Pub/Sub 模型中,生产者将消息发布到一个主题(Topic)中,订阅了该 Topic 的所有下游消费者,都可以接收到这条消息。如下图:



通常情况下,一个条消息只要被消费一次就行了,那么什么情况下需要所有的消费者都对这条消息进行消费呢?最典型的情况就是需要在内存中对数据进行缓存,并需要实时进行更新。例如,笔者做过一个违禁词系统,对用户输入的评论内容进行违禁词汇检测。这个违禁词系统,部署了在 N 台服务器上,为了提升检测性能,每台机器都会将违禁词库全量加载到内存中,词库的更新,是通过发送 MQ 消息来完成的。由于采用 Pub/Sub 模型,每台机器的 consumer,都可以接收到这条消息,直接在内存中更新敏感词库即可。

3、Partition 模型

为了解决在 PTP 模型下,有序消息需要通过"专有消费者”消费带来的性能问题,一些消息中间件,如 rocketmq,kafka 采用了 Partition 模型,即分区模型,如下所示:



生产者发送消息到某个 Topic 中时,最终选择其中一个 Partition 进行发送。你可以将 Parition 模型中的分区,理解为 PTP 模型的队列,不同的是,PTP 模型中的队列存储的是所有的消息,而每个 Partition 只会存储部分数据。对于消息者,此时多了一个消费者组的概念,Paritition 会在同一个消费者组下的消费者中进行分配,每个消费者只消费分配给自己的 Paritition。上图演示了不同的消费者可能会分配到不同数量的 Paritition。Paritition 模式巧妙的将 PTP 模型和 Pub/Sub 模型结合在了一起:


对于 PTP 模型:


一条消息只会由一个消费者进行消费,而 Partition 模型中每个分区最终也只会有一个消费者进行消费。对于通过"专有消费者"来保证全局消费有序的场景,在 Partition 模型中,只需保证创建的 Topic 只有一个 Partition 即可,这个 Paritition 最终也只会分配其中一个消费者。另外,在绝大部分场景下,我们没有必要保证全局有序,例如一个订单产生了 3 条消息,分别是订单创建,订单付款,订单完成。消费时,要按照这个顺序消费才能有意义。但是订单之间是可以并行消费的,例如将订单 1 产生的 3 条消息发送到 Partiton 1,将订单 2 产生的 3 条消息发送到 Partition 2,如此便达到了不同订单之间的并行消费。


对于 Pub/Sub 模型:


一条消息所有的下游消费者都可以进行消费。在 Paritition 模型中,只需要为每个消费者设置成不同的消费者组即可。然而,过多的消费者组,会给消息中间件运维带来麻烦。所以一些消息中间件,结合了 Partition 模型和 Pub/Sub 模型。例如 RocketMQ,支持为消费者组设置消费模式,如果是集群模式,就按照上述描述进行消费,如果是广播模式,就按照 Pub/Sub 模型进行消费。当然,Partition 模型也不全是优点,其最大的限制在于 Partition 数量是固定的(虽然可以调整),且只可以分配给其中一个消费者。当消费者的数量大于 Partition 数量时,这些多出来的消费者将无法消费到消息。一些消息中间件对此进行了优化,例如 rocketmq,支持单个 partition 的并行消费。即在对单个消费者内,同时启动多个线程,来消费这个 Partition 中的数据,当然前提是要求消息不是有序的,对于有序的消息,只能使用一个线程按顺序消费这个 Partition 中的数据。

4、Transfer 模型

Paritition 模型中的消费者组概念很有用,同一个 Topic 下的消息可以由多个不同业务方进行消费,只要使用不同的消费者组即可,不同消费者组消费到的位置单独记录,互不影响。?但是,Paritition 模型还是限制了消费者数量不能多于分区数。因此,又有了另外一种消费模型,笔者称之为 Transfer 模型,如下图所示:



生产者还是将消息发送到 Topic 中,针对一个 Topic,可以创建多个通道,这里称之为 channel。与分区不同的是,发送到 Topic 中的每条消息,都会转发到每个 channel,因此每个 channel 都有这个 Topic 的全量数据。当然,没有必要把真的把消息体完整的拷贝一份到 channel 中,可以只记录一下消息元数据,表示有一条放到这个 channel 中了。消费者在消费消息时,必须指定从哪个 channel 消费。多个消费者消费同一个 channel 时,每条消息只会有一个消费者消费达到,这一点与 PTP 模型类似。事实上,我们可以认为,消费了同一个 channel 的消费者,就自动组成了一个消费者组。但是,与 Partition 模型不同的是,这里没有分区的概念,因此消费者的数量可以是任意的。事实上,GO 语言编写的 NSQ 消息中间件,采用的就是这种模型。当然,这种模型与 PTP 一样,也不能保证被消息有序,除非通过类似于”专用消费者”的概念。


面试资料整理汇总




这些面试题是我朋友进阿里前狂刷七遍以上的面试资料,由于面试文档很多,内容更多,没有办法一一为大家展示出来,所以只好为大家节选出来了一部分供大家参考,需要全部文档的,关注小编后,点击这里即可免费领取


面试的本质不是考试,而是告诉面试官你会做什么,所以,这些面试资料中提到的技术也是要学会的,不然稍微改动一下你就凉凉了


在这里祝大家能够拿到心仪的 offer!

用户头像

VX:Lzzzzzz63 领取资料 2021.07.07 加入

还未添加个人简介

评论

发布
暂无评论
五分钟搞懂MySQL主从复制原理,附带学习经验