本文简单介绍一下分布式消息队列是什么、使用场景、以及两种模式,然后对其中之一——Kafka进行简单的概念介绍和入门知识点说明。
参考资料:
极客时间 Kafka核心技术与实战 胡夕 专栏
深入理解Kafka:核心设计与原理 朱忠华
分布式消息队列
消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以简单地描述为:当不需要立即获得结果,但是并发量又需要进行控制的时候,差不多就是需要使用消息队列的时候。
消息队列主要解决了应用耦合、异步处理、流量削锋等问题。当前使用较多的消息队列有RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq等,而部分数据库如Redis、Mysql以及phxsql也可实现消息队列的功能。
使用场景:
(1)应用解耦
多应用间通过消息队列对同一消息进行处理,避免调用接口失败导致整个过程失败。
比如库存系统,用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。这样一来,如果库存系统挂掉,用户下单功能也无法正常使用。
而使用消息队列后,在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了,从而实现了订单系统与库存系统的应用解耦。
(2)异步处理
多应用对消息队列中同一消息进行处理,应用间并发处理消息,相比串行处理,减少处理时间。
比如用户注册,发送验证邮箱和验证短信,可以从串行变成并行。
(3)限流削峰(削峰填谷)
这是应用得比较多也比较重要的一个场景。广泛应用于秒杀或抢购活动中,避免流量过大导致应用系统挂掉的情况。
当有秒杀活动时,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面;
秒杀业务根据消息队列中的请求信息,再做后续处理。
除了应用解耦、异步处理、流量削峰、消息队列还用于消息通讯(纯消息通信如聊天室)和日志处理(应用程序日志传输处理)等场景中。
两种模式
消息队列一般分为两种模式,一种是点对点模式,一种是发布-订阅模式
点对点模式
点对点模式:点对点模式包含三个角色,消息队列,发送者 (生产者),接收者(消费者)。
消息发送者生产消息发送到队列中,然后消息接收者从队列中取出并且消费消息。消息被消费以后,队列中不再有存储,所以消息接收者不可能消费到已经被消费的消息。系统A发送的消息只能被系统B接收。我们日常生活中的电话客服就属于这种类型。
发布-订阅模式
发布订阅模式:发布/订阅模式下包括三个角色,角色主题(Topic),发布者(Publisher),订阅者(Subscriber)。
发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。可能存在多个发布者向相同的主题发送消息,而订阅者也可能存在多个。
Kafka
Kafka起初是由LinkedIn公司采用Scala语言开发的一个多分区、多副本且基于ZooKeeper协调的分布式消息系统,现已捐献给Apache。目前Kafka已经定位为一个分布式流式处理平台,或者说是消息处理引擎,而不单单是消息队列,它以高吞吐、可持久化、可水平拓展、支持流数据处理等多种特性而被广泛使用。
Kafka之所以受到越来越多的青睐,与它所扮演的三大角色是分不开的:消息系统,存储系统,流式处理平台。
典型架构
一个典型的Kafka体系架构包括若干Producter、若干Broker、若干Consumer,以及一个ZooKeeper集群,其中ZooKeeper集群是Kafka用来负责集群元数据的管理、控制器的选举等操作的。
它是如何工作的?
Producter将消息发送到Broker,Broker负责将收到的消息存储到磁盘中,而Consumer负责从Broker订阅并消费消息。
基本概念
1、Broker
服务器代理节点,对于Kafka而言,Broker可以简单地看作一个独立的Kafka服务节点或Kafka服务实例,大多数情况下也可以将Broker看作一台Kafka服务器,一个或多个Broker组成了一个Kafka集群。
2、主题
Kafka中的消息以主题为单位进行归类,生产者将消息发送到特定主题,消费者订阅主题并进行消费。
3、分区
主题是一个逻辑概念,它还可以细分为多个分区,一个分区只属于单个主题,很多时候也会把分区成为主题分区。同一个主题下的不同分区包含的消息是不同的。分区可以分布在不同的服务器(broker)上。也就是说,一个主题可以横跨多个broker。通过增加分区的数量可以实现水平扩展,实现系统的高伸缩性。
4、副本
Kafka为分区引入了多副本(Replica)机制,每个分区下可以配置若干个副本。通过增加副本数量可以提升容灾能力。同一分区的不同副本中保存的是相同的消息,副本之间是“一主多从”的关系,其中leader副本负责处理读写请求,follower副本只负责与leader副本的消息同步(不对外服务)。副本处于不同的broker中。Kafka通过多副本机制实现了故障的自动转移,当Kafka及群众的某个broker失败时仍然能保证服务可用。
5、消息日志
Kafka使用消息日志来持久化数据,一个日志就是磁盘上一个只能追加写(Append-only)消息的物理文件,由于只能追加写入,避免了缓慢的随机I/O操作,改为性能较好的顺序I/O写操作,这也是实现Kafka高吞吐量特性的一个重要手段。
在Kafka底层,一个日志又进一步细分成多个日志端,消息被追加写到当前最新的日志段中,当写满了一个日志段后,Kafka会自动切分出一个新的日志段,并将老的日志段封存起来,并且在后台有定时任务会定期地检查老的日志段是否能被删除,从而实现回收磁盘空间的目的。
6、AR、ISR、OSR
分区中所有副本统称为AR,所有与leader副本保持一定程度同步的副本组成ISR,与leader副本同步之后过多的副本组成OSR。
7、HW、LEO
HW是High Watermark的缩写,俗称高水位,它标识了一个特定的消息偏移量(offset),消费者只能拉取到这个offset之前的消息。
LEO是Log End Offset的缩写,它标识了当前日志文件中下一条待写入消息的offset。
8、消费者组
消费者组是Kafka 的一大亮点设计。所谓消费者组,指的是多个消费者实例共同组成一个组来消费一组主题。这组主题中的每个分区都只会被组内的一个消费者实例消费。其他消费者实例不能消费它,但是这个分区也可以被其他的消费者组消费。消费者组里的所有消费者实例不仅“瓜分”订阅主题的数据,还彼此协助,假设组内某个实例挂掉了,Kafka能自动检测到,然后把这个实例之前负责的分区转移给其他消费者,这个过程就是“重平衡”。