Kafka简介(02)- Kafka基础概念

点对点消息系统

简单来说就是生产者(Producer)发送消息到队列,消费者(Consumer)从队列中取出消息。这种模型的特点就是一条消息只会被一个消费者接收,一但有消费者消费了这条消息,其他消费者就没办法重复消费了。



发布-订阅消息系统

发布订阅的模型也比较好理解,首先消费者需要订阅这个队列,生产者只要发送一条消息到队列中,所有已订阅该队列的的消费者都能接收到该消息,未订阅的用户则无法接收。就像我们的微信关注微信公众号一样,只有关注了的用户才会收到公众号推送的消息。



Kafka

Kafka异军突起,是非常火热的一款消息中间件。消息中间件的作用非常多,常用作系统业务的解耦。例如最常听到的秒杀业务,我们也能使用消息中间件对业务进行解耦,用户发起秒杀请求后,系统首先会将该请求转发到中间件中,然后返回一个等待的结果(用户界面显示正在抢购,请耐心等待),而我们系统会有监听器去接收这些秒杀请求进行对应的业务处理,最重要的是,整个系统的扩展显得非常简单,我们只需要部署Kafka的集群,以及后台的负载均衡就能快速提高系统的访问并发量。

Kafka的最大的特点就是高吞吐量以及可水平扩展,正因这两点Kafka非常适合处理数据量庞大的业务,例如使用Kafka做日志分析、数据计算。新版本Kafka也推出了Stream API,可以更好的支持数据流处理。基于这些特性我们可以实现非常多的系统功能。



Broker

Broker为节点的意思,我们启动的单个Kafka实例则为一个Broker,多个Broker可以组成Kafka集群。broker接收来着生产者的消息,为消息设置偏移量,并提交消息到磁盘保存,broker为消费者提供消息,对读取分区的请求作出响应,返回已经提交到磁盘上的消息,根据特定的硬件及其特性,单个broker可以轻松处理数千个分区以及每秒百万级的消息量。



集群

broker是集群的组成部分。每个集群都有一个broker同时充当了集群控制器的角色(自动从活跃成员中选举),控制器负责管理工作,包括将分区分配给broker和监控broker,在集群中,如果一个分区从属于一个broker,该broker被称为分区的首领。一个分区可以分配给多个broker,这时候会发生分区复制,这种复制机制为分区提供了消息冗余,如果有一个broker失效,其他broker可以接管领导权,不过相关的消费者和生产者都要重新连接到新的首领。

保留消息(在一定期限内)是kafka的一个重要特性,默认保留策略:要么保留一段时间,要么保留到消息达到一定大小的字节数,当消息达到上限时,旧消息就会过期并删除,所以在任何时间,消息总量都不会超过配置指定的大小。另外主题可以配置自己的保留策略,可以将消息保留到不再使用为止。还可以通过配置把主题当做紧凑型日志,只有最后一个带有特定建的消息会被保留下来,这种情况对于变更日志类型的数据来说比较适用,因为只需要关系最后时刻发生的变更。




多集群

如果越来越多的系统都发消息给kafka,那么最好适用多集群模式,原因包括:

数据类型分离

安全需求隔离

多数据中心(灾难恢复)

如果使用多个数据中心,就需要在它们之间复制消息,这样在线应用程序才可以访问到多个站点的用户活动信息,例如一个用户修改了他的资料,不管从哪个数据中心,都应该能看到这些改动,也可以多个站点的监控数据都聚集到一个部署了分析和告警系统的中心位置。不过,kafka本身的消息复制只能在单集群内进行,不能再多个集群间进行。

kafka的MirrorMaker工具可以实现集群间的消息复制,MirrorMaker的核心组件包含了一个生产者和一个消费者,两者之间通过一个队列相连。消费者从一个集群读取消息,生产者把消息发送到另一个集群上,不过这种方式在创建复杂的数据管道方面显得有点力不从心。




Topic

Topic为主题的意思,也就是相当于消息系统中的队列(queue)。kafka的消息通过主题进行分类,主题就好比数据库的表,或者文件系统里的文件夹,一个Topic中存在多个Partition,一个分区就是一个提交日志,消息以追加的方式写入分区,因为无法在整个主题范围内保证消息的顺序,但可以保证消息在单个分区内的顺序。很多时候,人们把一个主题的数据看成一个流,不管它有多少个分区,流是一组从生产者移动到消费者的数据,Kafka Streams等这些框架以实时的方式处理消息,也即是所谓的流式处理。可以用流式处理和离线处理进行比较(例如Hadoop)。



Partition

Partition为分区的意思,是构成Kafka存储结构的最小单位,kafka通过分区来实现数据冗余和伸缩性,分区可以分布在不同的服务器上,也就是说一个主题可以横跨多个服务器,以此来提供比单个服务器更强大的性能。



Partition offset

offset为消息偏移量,以Partition为单位,即使在同一个Topic中,不同Partition的offset也是重新开始计算(也就是会重复)



生产者

生产者创建消息,也被称为发布者或者写入者,一般一个消息会被发布到一个特定的主题上,一般情况会均衡的分布到主题的所有分区上,而并不关心特定消息会被写到哪个分区,不过,某些情况也可以写到指定分区,这通常是通过消息键和分区器来实现。分区器为键生成一个散列值,并将其映射到指定分区上,这样可以保证同一个键的消息会写到同一个分区上,在某些情况下可以实现顺序性。分区器也可以自定义。




消费者

消费者读取消息,也可以叫做订阅者或者读者。消费者订阅一个或者多个主题,并按照消息生成的顺序读取它们。消费者通过检查消息的偏移量来区分已经读取过的消息,偏移量是另一种元数据,它是一个不断递增的整数值,在创建消息时,kafka会把它添加到消息里,在给定的分区里,每个消息的偏移量都是唯一的,消费者把每个分区最后读取的消息偏移量保存在zookeeper或者kafka上,如果消费者关闭或重启,它的读取状态不会丢失。




Group

Group为消费者组的意思,一个Group里面包含多个消费者,也就是说,会有一个或者多个消费者共同读取一个主题,群组保证每个分区只能被一个消费者使用。消费者与分区之间的映射通常被称为消费者对分区的所有权关系。通过这种方式,消费者可以消费包含大量消息的主题,而且如果一个消费者失败,群组中其他成员可以接管失效消费者的工作。



Message

Message为消息的意思,Kafka的数据单元被称为消息,可以把消息看成是数据库里的一行或者一条记录。消息由字节数组组成,所以对于kafka来说,消息里的数据没有特别的格式或者含义,消息可以有一个可选的元数据,也就是键(key),键也是一个字节数组,同样没有特殊的含义。当消息以一种可控的方式写入不同的分区时,会用到键。最简单的例子就是为键生成一个一致性散列值,然后使用散列值对主题分区数进行取模,为消息选取分区,这样可以保证具有相同键的消息总是被写到相同的分区上。

这里就需要说说为什么这样设计了:

首先Topic中有分区的概念,每个分区保存各自的数据,而我们的Group这对应着Topic,也就是这个Topic中的数据都是由该Group去消费,也就是允许多个消费者同时消费,这样能大大提高Kafka的吞吐量。不过这样的设计也会带来不少的不便,比如特定场景下你需要去维护多个Partition之间的关系。这里就不多讲了。



批次

为了提高效率,消息被分批次写入kafka,批次就是一组消息,这些消息属于同一个主题和分区。如果每一个消息都单独穿行于网络,会导致大量的网络开销,把消息分成批次传输可以减少网络开销,不过,这要在延迟和吞吐量上作出权衡,批次越大,单位时间处理的消息也越多,单个消息的传输时间就越长。批次数据会被压缩,这样可以提升数据的传输和存储能力,但是要做更多的计算处理。



模式

对于kafka来说,消息就是晦涩难懂的字节数组。所以有人建议使用一些额外的结构来定义消息内容,这样更加容易理解。根据需求,消息模式有许多可用的选项。想JSON和XML这些简单的系统,易用而且可读性好。不过它们缺乏强类型处理能力,而且不同版本的兼容性也不是很好。许多kafka使用者喜欢用Apache Avro,它最初是为Hadoop开发的一款序列化框架,Avro提供了一种紧凑的序列化格式,模式和消息体是分开的,当模式发生变化时,不需要重新生成代码,它还支持强类型和模式进化,其版本既向前兼容也向后兼容。

数据格式的一致性对kafka很重要,它消除了消息读写之间的耦合性,如果读写操作紧密的耦合在一起,消息订阅者则需要升级系统才能同时处理新旧两种数据格式。在消息订阅者升级了之后,消息发布者才跟着升级,以便使用新的数据格式,新的应用程序如果需要使用数据,就要与消息发布者发生耦合,导致开发者需要做很多繁杂的工作。定义良好的模式,并把它们放在公共仓库,可以方便我们理解kafka的消息结构。

你可能感兴趣的:(Kafka简介(02)- Kafka基础概念)