消息队列:
当一个服务处理量为100,而另一个服务发送量为200,这时候多余的消息会被丢弃,如果想要全部处理,我们必须加入队列,这个队列用来存储消息的信息,通过offset表示当前处理的位置。注意此时队列还位于进程中,也就是服务进程,我们的进程一旦挂掉,未被处理的消息会直接丢失,我们不希望这样,所以独立出来单独一个进程,用来存放队列,这样避免了受服务端的影响。
这个独立出来的用来存放消息的队列,就是我们说的消息队列。
消息中间件:
要想把消息队列变得更高性能,并且高可用,还可扩展,我们需要将他进化为消息中间件。一个强大的消息中间件例如kafka这种的可以流量削峰,完成大多数业务场景所需要的功能,
那么一个满足高可用性,高性能以及可扩展的消息队列进程,也就是一个成熟的消息中间件。
为什么时候需要用到消息中间件?
当我们维护A服务和B服务两个进程,B服务每秒只能处理100个请求,而A服务每秒发送200个请求时,在B进程当中写一个队列,用于存放无法处理的请求,在之后能处理多少处理多少,处理不掉的我们进行报错或者直接丢弃。这时候如果B服务宕机,那么消息队列中的数据就会直接丢失,想避免这种情况,我们将消息队列独立出来单创一个进程。
队列说白了就是一个链表,每个消息对应一个节点,每个节点有自己的序号offset值,记录消息的位置。消费者线程依据自己的能力,消费链表里的消息,能处理多少处理多少,当消费者服务处理一条消息后,不断更新offset代表已处理消息的个数。
这时候有一个问题,队列里面的消息存储在消费者线程的内存里,如果来不及处理就宕机了,这些消息就会丢失,所以我们将队列挪出来,变成一个单独的进程,这时候就算B服务重启,也不会被影响,这个独立出来的队列进程就是消息队列。
而像A服务这样发送数据到消息队列的角色就是生产者producer,而B服务这样负责处理消息队列中数据的角色就是消费者consumer
这时候消息队列虽然不受其他进程影响,但是太基础了,如果数据量过大也无法发挥其作用,无法保证高可用性,高性能,高扩展性,怎么去保证,需要用到消息中间件,我们一步一步去过渡。
什么是高可用性,高性能,高扩展性呢?
首先,我们可以给消费队列两端加入更多的消费者和生产者,提高请求产生和处理效率。
其次,我们给消息队列进行分片,先将消息分类成不同的topic,每个topic被分配到对应的position,当单机存有多个position的时候,容易占用cpu和内存较高的情况,影响性能,这时候分给不同的机器,这每个机器对应一个broker,依据是根据请求的类型去划分为不同的topic,相同topic存放在一个broker进行处理,保证了请求消息的规律性。
最后,加入持久化,在数据丢失时我们确保能保留大部分信息即可,持久化是通过broker的备份,leader用来正常处理消息请求,follower只负责记录leader的备份信息,当leader挂了以后,会推举一个follower作为新的leader,以此实现消息的持久化。
同时,通过zookeeper组件来监控各个组件的状态,定时去判断broker的状态,保证程序正常运行。
这样一来,在做好了消费者生产者集群,分区分片进行部署,消息的持久化以后,消息中间件就完成了。
当然,每个请求通过唯一的UUID来保证幂等性,由于网络原因产生的多个请求操作,也只会产生一次影响。
总结一下:
partition:队列分片 ,备份即为follower,正常处理消息则是leader。
broker:部署的机器,上面有多个partition,增加broker可实现可扩展性。
consumer group:多个消费者形成的消费者组,处理对应类型的topic可提高性能。
topic:消息类型,通过key或者其他值来计算,对应的类型由对应的partition传给consumer group。
死信队列:处理重复失败的消息,包含确认机制。
replication:由partition,一个leader和多个follower组成(分布在不同的机器上),当一个leader挂了,由其余follower推举出新的leader,实现高可用。
高性能:通过partition队列分片,以及多台机器broker,同时增加消费者组consumer group,提升处理消息的能力,增大吞吐量。
高可用:通过不同broker上面的replication完成,还有当所有broker挂了时,消息也会持久化在硬盘里,也就是服务器中,实现高可用性。
可扩展性:不仅可以增加消费者线程,还可以增加生产者,提升吞吐量,而且可以增加机器broker来实现队列的扩充,只需要分配对应的topic即可。
最后是应用场景:相较于RocketMQ,kafka的topic也就是消息类型较少,而且无死信队列,所以他只负责高并发的处理消息而不负责检查消息是否正确被处理,所以在一些抢购的场景我们需要使用RocketMQ,死信队列可以解决失败消息的处理。
版权归原作者 小卢在成长 所有, 如有侵权,请联系我们删除。