00:00
啊,那接下来我们再来看啊,前面提到消息队列中消费者去更新呃,获取数据的两种方式啊,那第一种的话就是推的一种方式啊,由消息队列推给发送者啊,推给消费者,然后第二种的话就是啊,消息队列主动去拉取的方式。这两种方式的话啊,其实从消息的实时性上面来说的话,推送的方式实时性啊,比拉的方式要强啊,但是呢,从其他方面来看啊,你比如说从消费者的处理速度来看的话,那推送的方式,推送的方式它其实是要。它的推送发送速率呢,由消息队列本身控制,而下游下游呢,不同的消费者消费速度不同,这种模式下面其实对啊,下游的不同消费者呢,很难做到一个很好的匹配,而拉取的方式呢则啊。不相同就是它可以呃是按照消费者按照自己的一个消费速率去呃,按需拉取上游的一个按呃消息队列里面的数据来做消费啊,当然其实在队列内部维护的实现维护的时候呢,啊推出的方式,其实消息队列只需要维护一些哪些消费者订阅了哪些主题,然后呢啊导有消息时呢,向对应的消费者呢推送数据,而拉取的方式呢,则需要啊由消费者主动去不断的去龙群啊去。
01:31
询问这个消息队列是否有数据啊,然后再来去有的话再去返回给消费者去消费啊,开源组件里面其实都有使用这些方式啊,比如说rabbit MQ和active MQ,其实他们用推速的这种方式,而像拉的方式更加的灵活,用的也更多,像卡夫卡,Rockie的MQ,帕萨等等,其实。都有使用跑呃拉取的方式来去实现啊,其实在从资源消耗层面来看的话啊,那对于推送的时候呢,因为不同的消费者消费速度不同,那呃极有可能会出现一些啊推送消息的时候失败的场景,那失败的这种场景里面呢啊,其实大部分的时候需要消息队列内部呢维护一些啊消息重试缓呃消息的缓冲,然后做一个消息的重试。
02:21
就是拉就不存在这种这一类的问题。啊,这其实就是推送和拉取的两种方案的一个对比吧,其实这两种方案啊,在往往其实也不局限于消息队列,其实在往往啊一些数据获取的这种啊,双方之间呢,往往都会存在这种,比如说像业务里面的一些给啊用户推推送红点等等,以及啊就是像在以网络编程里面来举例的话,那IO多路复用中一破,其实它的实现里面呢,其实从绿核和用户这一个层面来看,那。也其实也有点像推送的这种方式,就是瑞核呢,将数据就绪的通知呢,推送给上层的用户,然后呢,再由上层用户再去读取数据啊,他这儿推送呢,是一个推送呢,是一个啊通知,而不是推送的数据啊,其实这这也是一个广义的一个推拉的一个对比。
03:16
啊,接下来这一节我们再来看消费者这边的一个消费模型啊,其实消费者这边的一个消费模型里面的话啊,我其实总结成了一个一比NBM的一个关系啊,这个关系呢,主要我们来下面再来一点一点解释。啊,就是其实在消费消费者这边消费的时候呢,那最简单的一个队列模型呢,它就是生产者生产一条数据发给队列啊,消息消息队列里面,那消费者呢,从这个对头里面去取数据啊,就是一发一收的这个,这其实是最简单的一个队列模型。而往往在我们的消息队列里面呢,其实往往会处理以下几种几种场景,第一种的话就是这一份数据其实需要被不同的业务方去使用,或者不同的场景里面去使用,那其实就变成了啊,一个一对多的关系,其实这呢,其实一比N,其实就描述的是这种一对多的关系,一份数据被N方去使用,而这个每个不同的不同的。
04:13
使用方呢,或者是使用场景呢,其实我们就称就是啊,往往呢,会把它归为一个消费者组。啊,这也就是一比N,就是一份数据被N个消费者组去消费啊,然后呢啊在这种生产者生产速率远远大于消费速率的时候呢,那就会造成一个啊消息的一个堆积,其实往往在这种情况下,为了减少消息的堆积,提升消费的速率,就是消费一个消费者组里面呢,往往会有啊会管理多个消费者,也就是这M的关系,就是M就表示的是啊一个消费者组里面对应M个消费者,所以一比N比M就是啊一份数据备N个消费者组啊去消费,同时呢,每个组里面会有M个,M是一个变量,M个消费者去消费啊,那在这种模式下面,其实就往往就啊出现了一个发布订阅的模型啊,它的特点就是啊以。
05:09
一份数据在这个多个组之间呢,是广播的方式去啊分发,而在这个组内部呢,往往是一条数据只能被一个消费者组中的一个消费者去使用啊这样一个模型,然后其实往往在这个地方往往还存在两个特点,第一个就是啊,其实往往在一些消息队列实现的内部呢,啊,其实这儿的一个队列,这种队列啊,逻辑上的队列啊,其实往往他们会将一个我们的一个主题会话拆分成多条队列,也就是在消息队列内部的话,会有这个平行的多个队列去存储我们的数据,那往往就会出现第一个问题就是啊,生产者这边发送数据的时候,到底要一条数据发给哪一个队列呢?就内部其实有多个队列,那存在一个负载均衡的选择,就是往往呢也会选择啊,像随机或者龙群以及呢,是支持局部的局部顺序的这种按照呃消息的一个K去做哈希这种方式。
06:07
啊,这就是生产者这边一个啊,消息的一个负载均衡的特点,第二个就是消费者这边啊一个。一个消费者组里面其实有M个消费者,那在这里面他的比如说队列有P个队列的话,那存在一个多对多的一个分配,其实往往啊分配的方式呢,就是为了。降低一个竞争,往往呢,就是一个消费者可以去啊,他去管理啊,他去消费其中的一一个队列啊,就是一个消费者可以去,就是一个队列只能被一个消费者去啊消费,而一个消费者呢,可以消费多个队列,大概就是这个意思啊,所以这也总结就是啊,一般呢,一个队列呢,只能被一个消费者组中的一个消费者去消费,但一个消费者呢,可以去消费多个队列啊就是这样一个概念。啊,这其实就是消费者其实啊,整个的一个消费模型,一比N1比N比M的一个关系啊,它中间也涉及到一个生产者的一个负载均衡,以及消费者的一个负载均衡。
07:10
啊,那前面其实我们所有的消息队列的一些主流的设计思想,其实就介绍完了,介绍完之后我们这些啊来将主呃,就是用的比较多的像卡夫卡,帕萨以及如给MQ的这几个架构呢,我们这儿呢,来做一个整体上的一个啊回顾整体的一个啊浏览,比如说最左侧上角右呃左上角的这个呢,就是卡夫卡的一个架构,就是它从从数据的一个流向可以看到,就是上面呢是生产者,多个生产者中间呢是我们的消息队列集群,然后下面呢是一个消费者啊,每个圆圈里面呢,就是套的一个消费者组。啊,这其实就符合我们前面介绍的啊,它的一个消费者的一个主体的模型,以及它内部的一个啊消费者的模型,以及这边的一个负载均衡啊其实对于帕萨它也是一样,就上面是生产者啊,同时呢啊中间是我们的一个消息队列的集群,这边呢,又是一个消费者数据的流向呢,就也是就是这样一个从生产者流向消息队列,再流向我们的消费者,而rockie MQ呢,这边其实有呃两个架构,第一个的话就是它的4.5以前的主从架构啊,主从架构的话就是左边的生产者,那右边的消费者,中间呢,就是我们的集群,集群里面啊其实可以看到它其实是拆分成了多个多个小的集群啊,就是每一个集群呢,就是一一组master s slave1对啊,就是一个小集群,而4.5以后的版本呢,其实它就是将中间的集群呢,换成了按照啊。
08:46
开源社区里面的一个顶这样一个rapft架rap库去啊,封装的一套鸡群啊,所是它这里面每一套呢,就是一一个rapft小鸡群啊,就是有leader角色,然然后呢,另外两个就是呃,Follow角色啊,数据的复复制,那按照rap的算法去复制,整个呢是一个强一致性的一个一套架构,其实整体来看的话,它其基基本上都是这样一套架构,只不过在这边其实呃还多了一个角色,就是原数据的一个维护中心,像卡夫卡跟帕A里面都是采用keepper去维护它的一些集群的原数据,而像rockie MQ里面,它整个采用的叫做name serve这样一个集群去维护它的name server呢,其实啊,就简单的就是一个无状态的一个集群啊,这其实是整体他们架构的一些特点。
09:38
啊,这一节我们再来对卡夫卡和IEMQ啊做一个数据数据组织上面的对比,其实在卡夫卡里面左边呢,其实是一个卡不卡内部的一个集群啊,就是它三个节点构成的一个集群里面的话啊,对于一个topic来说啊,它比如说我们就是一个三分区啊,然后啊两个副本。
10:00
加起来就是六分,数据来说的话,卡不卡它里面的数据呢,它其实是一个topic,会分成多个partition,每一个partition呢,又会有他自己的副本,然后在这个过程中的话,那。其实就。啊,就对于啊,在卡不卡里面,它的partition,其实呃,它的副本呢,是会分散在多个集群内部,然后呢,数据的啊,同步方式也是以我们的partition作为单位去维护的,就是每个partition副本之间呢,它会选出一个Li,其他的follow,然后这种方式去同步,而我们来看对于rocket MQ里面啊,它的特点呢,是。首先它里面集群里面会有多个小集群,就是我们前面提到的一组master slave就是一组集群,所以在这边的话,我们可以看到它其实第一组的话就是它一个topic,它首先会按照集群去分分片,就首先我们一个topic I会分成集群,集群一的一个topic,集群二的topic,集群三的topic,然后这么拆分了之后,每一组集群之间可以根据它齐群的一个啊性能特点以及配置,然后拆分成啊这个每一个分片里面呢,又可以拆分成多个队列,比如说集群A啊,比如说集群A,比如说集群一的话,它的性能啊中等,就拆了两个队列,然后集群二呢,它的配置比较强,拆出了三个,集群三呢可能配置比较弱,就拆了一个,然后呢,所以它的topic首先分的就是按照集群去分片,首先分片成啊集群的topic a啊分片的topic a,然后每一个A呢,啊,集群内部又会去拆分成多个队列,其实就类似于我们这边的帕啊,然后这样拆分了之后,它的数据同步的方式呢,啊又是。
11:41
是按照每组集训之间master跟slave去同步的,所以这其实是啊,Rocket MQ和卡夫卡之间他们数据的一个同步,以及组织的方式的区别。就就是卡夫卡里面,它其实只有一层啊,它就是三个节点只有一层啊,它的数据的副本呢,是打散在part维度,打散在多个broke之间,而IEMQ,它是首先按集群去封片,封片完了之后在每个集群内部再去做一个逻辑队列的一个拆分。
12:12
啊,那我们再来看rockie m卡夫卡和rock MQ他们之间的一个存储模型上面的一个对比,其实存储模型上面对比以一个三分区单副母的为例的话,那前面提到其实一个topic在卡夫卡里面会拆分成三个队列,那每一个队列就叫叫做帕,这每一个队列呢?它是一个逻辑上的对联,那物理上实际存储的时候呢。它又是以sIgMa为sIgMa的段作为一个单位去存储的,那。一个队列会有多个段组成,那每一个段里面呢,它的数据呢又包含三部分,第一部分的话就是一个啊存储真实数据的一个数据文件,点logo文件,第二部分的话就是索引文件,那索引文件中又分为两个,第一个的话就是点ENE文件,这个存储呢,就是每条消息啊,它写在了这个点log文件的什么位置,就是这样一个映射关系。第二个的话就是按照时间从哪一个就是什么时间写入的哪条消息啊类似于关系性数据库里面的一个二级索引啊,这里面存储的就是啊里一条消息,一个编号,这个这条消息啊写的磁盘的哪个位置啊,这里面存的就是什么时间,时间戳写入了第几条消息这样一个顺序,所以它逻辑上面数据是一个啊逻辑对列,物理上存储又是按照这样方式去组织的,然后点漏O文件呢,就是按照我们的啊数据写的方式去将数据啊写入到我们的。
13:36
啊,S的点数据文件里面,那查询的时候呢?啊,对于数据的查询,那就是首先去查找我们的inex这条index呢?啊,我们的消息,消息按照编号去查询inex,找到对应的inex之后呢,再去点那个文件里面去查,大概就是这样一个过程,而在rocket MQ里面呢,啊,同样以一个三分区个副本为例的话,那就是三个集群啊,Master,零集群,集群一,集群二,在这里面的话。
14:04
呃,它的一个数据拆分呢,跟卡夫卡不一样,首先它的一个每一个集群,每一个节点里面呢,有一个保存数据的,就是数据文件的一个保存真实消息数据的一个数据文件,就是com log啊,这个文件呢,其实它是所有的啊,一个节点内部的所有topic都会去公用这一个文件。就是topic a topic b topic c数据都会存在com log,那具体它其实是在索引层面去拆分的,那每个topic呢,它会对应一个媒体,就是拆分成多个队列之后呢,那每一个队列它有一个它自己的偏移量啊,自己的这个队列里面其实存储的就是一个啊它的偏移量啊,那这个偏移量呢,其实就对应的是哪条消息写的这个copy米个什么位置,然后呢,它的一个哈希值是多少啊,开的哈希值是多少,方便用开区过滤消息,按照这个方式,同时呢,它也支持按照时间范围以及而消息ID啊去查找消息,也有一个inex文件,本质上这个文件呢,其实就是啊,它呢也是这个集里面去的,它本质上也就是按照我们的啊哈哈,Ma的方式,将这个数据呢的磁盘在M这里面的时候,它所有的这些数据呢,都是都是按照定去固定的,就是规大小啊,比如说就是一个G,然后呢啊,假如说。
15:26
出定之后呢,那每个文件的命名呢,也就是以啊我们的一个偏就是文件的一个大小去数据命名,比如第一个就是零,第二个就是一级的那个啊一个数字,然后这样命名,它逐渐是有序的,那数据在存储读,这样保证呢,它写的时候是按照顺序写去写,然后读的时候呢,它是采用f map来去加速一个读的一个过程啊,同时其实在卡这儿少说的一句,其实卡夫卡里面它的数据的文件命名也是按照一个消息的一个偏移量去命名的,就这第一条消息,比如这一一百零一条消息这儿200。
16:02
250条消息,所以找一条消息的话,那大概就是按照一个首先二分定位到某一个段里面,某一个段里面再去找索引,索引找到之后再去数据文件找数据啊这样一个过程,这其实是卡夫卡和rock MQ他们之间存储模型上面的一个区别。啊,那这一节的话就是我们来看再看一下卡夫卡和帕萨他们之间的一个对比啊,其实卡夫卡它是逻辑上面是以以这个partition为维度去存储数据的,那一个part属于一个broke,那一个partition里面可以看到,其实它所有的数据呢都会存在啊,都是按照逻辑分段去存储在我们的broke内部啊其实在这种特点上面呢,就有几个问题,第一个的话就是集群呢,它的容量呢,容易受到这个节点的最小容量限制,第二个的话就是集群的扩展呢,其实需要对这个分区呢做一个重新的平衡啊,这个呢其实比较消耗网络和啊网络带宽,然后第三个的话就是如果在这种场景下面丢失一个副本的话,其实需要重新复制完整的这一个分区啊才可用。
17:07
啊,这是整个一个啊卡夫卡其实这样设计之后的一个它的特点吧,也带来的一个缺陷,而在帕萨里面的话,它其实逻辑上面也是数据按照一个帕提去去存储的,只不过它的提式里面,它的数据也是按照分段,但是呢,在底层存储的时候,前面提到其实它的数据存储是按照我们的book keepper这样一个分布式啊日志库去存的,那数据它是一个去中心化,每体每个sment呢,虽然也都是保存了三段,但是呢,它是会打散在底层存储的多个集群上面去达到一个条代化的写入,在这种方式下面的话,那其实如果说需要扩展的话,只需要这边加节点,数据就会自动的写入到这边的另外的一个存储节点上面去,所以在这种特点上面,就是集群中的数据呢,其实它分布的比较均衡,扩展式呢,不需要拷贝和重新平衡,同时呢,如果说有节点坏掉之后,数据坏掉之后呢,它其实可以通过其他节点来做一个修复,而减少的一个全量的。
18:07
拷贝,这其实是卡夫卡和帕萨他们存储上面的一个区别啊,然后。其实关于卡普卡和帕萨最详细的原理,我们后面会在后面的内容呢,再进行一个详细的一个介绍。啊,其实前面呢,我们就将所有的消息队列的一些设计思想的内容呢,做了一个啊介绍,然后主要呢,其实再回顾一下,就是首先呢,介绍到消息队列的几个适用场景啊,像异步解舞、学风,然后接下来介绍了这些场景之后呢,又介绍了有哪些消息队列,以及他们之间的一些特点,一些差异啊介绍完这些对比之后的话,我们其实就介绍了这些消息队列到底在设计的时候有哪一些通用的一些思想值得借鉴和直接参考啊,比如有介绍了它的一个主体的模型啊,就包含几个角色,然后呢,每一个除了它的主页主主体模型之外,我们又重点介绍了一个消息队列存储方案的选型,是选择内存来存储数据,还是选择磁盘来存储,那内存存储的时候怎么样去保证消息的一个可靠性,同时呢,内存存储的时候怎么样去啊,让我们的数据呢能够更好。
19:23
的就能够存储更多的数据啊,如果磁盘的时候呢,又怎么样去提升一个磁盘的性能啊,顺序写,然后怎么样去减少一个访问磁盘的次数,以及怎么样去加速磁盘读写的一个效率等等啊,然后接下来呢,其实又介绍了消息队列中很重要的一个消息,消息的一个消费模型,同时呢,在那边也介绍了消生产的负载均衡方案,以及消费者的一些负载均衡的方案,然后最后呢,对主流的消息队列啊,就是中间件呢架构做了一个整体的一个对比和总结,也对卡夫卡和rie MQ以及卡夫卡和帕卡。
20:00
他们整体的一个存储模型做了简单的介绍,因为后更加深层次的内容,其实会在后面的内容我们再来进行详细的介绍啊,其实这一部分主要的一个设计思想啊,详细的一个内容其实就介绍完了,下面呢会呃,重点介绍每一个组件,他们内部的一些实践原理,以及内部的一些实践机制。
我来说两句