kafka核心
kakfa核心
- topic
- topic类似于文件系统中的文件夹,事件就是该文件夹的文件。
- kafka中的主题总是多生产者和多订阅者,一个主题可以有零个、一个或多个写入事件的生产者,订阅者同样如此。可以根据需要随时读取主题中的事件。
- 与传统消息传递方式不同,事件在消费之后不会被删除,相反,你可以通过每个主题的配置设置来定义kafka应该保留事件的时间。
- topic是分区的,意味着一个主题分布在位于不同kafka代理的多个桶上,数据的这种分布式放置有一个好的伸缩性,因为它允许客户端应用程序同时向多个代理读取和写入数据。当一个新事件发布到一个主题时,实际上被附加到该主题的分区之上,具有相同事件键的事件被写入同一分区,并且kafka保证给定主题分区的任何消费者将始终以写入事件完全相同的顺序读取该分区的事件
- 为了数据具有容错性和高可用性
- 每个主题都可以复制,甚至跨地理区域或数据中心复制,以便始终有多个代理拥有数据副本
- 在设置副本时,副本数是必须小于集群的broker数的,副本只有设置在不同的机器才有作用
- 分区(partition)
- 无分区时,一个topic只有一个消费者在消费这个消息队列,采取分区后,如果有两个分区,最多两个消费者同时消费,消费的速度肯定也会更快
- 备注
- 一个parttition只能被同组的一个consumer消费
- 同一个组里的一个consumer可以消费多个partition
- 消费效率最高的情况是partition和consumer数量相同,这样确保每个consumer专职负责每一个partition
- 副本(Replica)
- topic下会划分多个分区,每个分区都有自己的副本,其中一个是leader,其余的是follower副本。
- kafka通过轮询算法保证leader replica是均匀分布在多个broker上
- replica均与分配在broker,同一个partition的replica不会再同一个broker上
- 同一个partition的replica数量不能多于broker数量,多个replica为了数据安全,一台server存多个replica,server挂掉,上面的副本都会挂掉
- 分区的leader replica均衡发布在broker上,此时集群的负载是均衡的(分区平衡)
- 消费者
- kafka消费者工作原理
- 消费者是一个从kafka cluster中消费数据的一个客户端,消费者维持一个tcp的长连接来获取数据,使用未能正常关闭这些消费者问题就会出现,(消费者不是线程安全的)
- 工作流程
- consumer发送joinGroup请求
- coordinator选择一个consumer作为leader,把要消费的topic情况告诉给leader consumer
- leader consumer会制定消费方案,把消费方案发送给消费组协调器(coordinator)
- 消费者概念
- 消费者组初始化
- 协调器
- 协调器是用于协调多个消费者之间能够正常工作的一个角色,比如计算消费的分区分配策略,又或者消费者的加入组与离开组的处理逻辑(kafka控制器的角色)
- 协调器分类
- 消费组协调器(GroupCoordinator)
- 消费者协调器(ConsumerCoordinator)
- 消费组协调器
- 各个消费者协调器的中央处理器,每个消费者的所有交互都是和组协调器进行的
- 主要负责如下工作
- 选举leader消费者客户端
- 处理申请加入组的客户端
- 再平衡后同步新的分配方案
- 维护与客户端的心跳检测
- 管理消费者已消费偏移量,并存储至_consumer_offset中
- 消费者协调器(consumerCoordinator)
- 每个客户端都会有一个消费者协调器,主要作用就是向组协调器发起请求做交互,以及处理回调逻辑
- 每个consumer实例化时,同时实例化一个消费者协调器(consumerCoordinator),负责同一个消费组下各个消费者
- 主要是负责如下工作
- 更新消费者缓存的metaData
- 向组协调器发起入组请求和离组请求
- 消费者加入组后的相应处理
- 向组协调器发送提交已消费偏移量的请求
- 保持与组协调器的心跳进程
- 向协调器发起同步组请求(如果是leader客户端,还会计算分配策略数据放到入参传入)
- 消费偏移量管理
- consumer在消费过程中可能会出现断电宕机等故障,consumer恢复后,需要从故障前的位置继续消费,所以consumer需要实时记录自己消费到哪个offset,以便故障恢复后继续消费
- consumer默认将offset保存在kafka一个内置的topic中,该topic为_consumer_offsets
- offset的方式
- 自动提交offset
- 手动提交offset
- 手动提交方式有两种:同步提交(commitSync)和异步提交(commitAsync)
- 同步提交
- 阻塞当前线程,一直到提交成功,有失败重试机制,吞吐收到影响
- 异步提交
- 没有失败重试机制,故有可能提交失败
- 无论是同步提交还是异步提交都有可能造成数据的漏消费或者重复消费。先提交offset后消费,有可能造成数据的漏消费;而先消费后提交offset,有可能造成数据的重复消费
- 自定义存储offset
- offset的维护相当繁琐,因为需要考虑到消费者的Rebalace
- 当有新的消费者加入消费组,已有的消费者退出消费组或所订阅的主题的分区发生变化,就会触发到分区的重新分配,重新分配的过程叫做Rebalance
- 消费者发生Rebalance之后,每个消费者消费的分区就会发生变化,因此消费者要首先获取到自己被重新到的分区,并且定位到每个分区最近提交的offset位置继续消费
- 消费者分区分配策略
- 消费者组初始化
- kafka消费者工作原理
- 特点:
- 高可用性
- kafka本身是一个分布式系统,同时采取Zookeeper存储元数据信息,提高高可用性
- kafka使用多副本机制,当状态为Leader的partition对应的broker宕机或者网络异常时,kafka会通过选举机制从对应的Replica列表中重新选举出一个Replica当做leader,从而继续对外提供读写服务
- 可靠性
- 从producer端来看,可靠性是指生产的消息能够正常的被存储到partition上消息不会丢失。kafka通过
Request.required.acks
和min.insync.replicas
两个参数配合,在一定程度上保证消息不会丢失 - request.required.acks可设置为1、0、-1三种情况
- request.required.acks = 1。设置为1时代表leader状态的partition接收到消息并持久化时就认为消息发送成功。如果isr列表的replica还没来得及同步消息,leader状态的partition对应的broker宕机,则消息有可能丢失、
- request.required.acks = 0。设置0时代表product发送消息就认为成功,消息有可能丢失
- request.required.acks = -1。设置为-1时,代表isr列表中的所有replica将消息同步完成后,才会认为消息发送成功;但是如果只存在主partition的时候,broker异常时同样会导致消息丢失。所以此时就需要
min.insync.replicas
参数配合,该参数需要设定值大于等于2,当partition的个数小于设定的值时,producer发送消息会直接报错
- 注意:
- 假设如果消息在同步到部分从partiton上时,主partition宕机,此时消息会重传,虽然消息不会丢失,但会造成同一条消息存储多次。新版本kafka提出幂等性,通过给消息设置一个唯一的ID,并且该ID可以唯一映射到partition的一个固定位置,从而避免消息重复存储
- request.required.acks = 1。设置为1时代表leader状态的partition接收到消息并持久化时就认为消息发送成功。如果isr列表的replica还没来得及同步消息,leader状态的partition对应的broker宕机,则消息有可能丢失、
- 从producer端来看,可靠性是指生产的消息能够正常的被存储到partition上消息不会丢失。kafka通过
- 一致性
- 从consumer端来看,同一条消息在多个partition上读取的消息是一致的,kafka通过引入HW(High Water)来实现这一特性
- 假设consumer从主partition1上消费消息,由于kafka规定只允许消费HW之前的消息,所以最多消费到message2。假设当partition1异常后,partition2被选举为leader,此时依旧可以从parttition2上读取到message2(木桶效应)
- 使用HW特性后会使得消息只有被所有副本同步后才能被消费,所以在一定程度上降低消费的性能,可以设置Replica.lag.time.max.ms参数来保证消息同步的最大时间
- 数据传输的事务
- 数据传输的事务定义通常由以下三个级别:
- 最多一次:消息不会被重复发送,最多被传输一次,但也有可能一次不传输
- 最少一次:消息不会被漏发送,最少被传输一次, 但也有可能被重复传输
- 精确的一次:不会漏传输也不会重复传输,每个消息都传输
- 数据传输的事务定义通常由以下三个级别:
- 实现高吞吐、以及快
- 顺序读写
- 对于磁盘,如果是随机写入数据的话,每次数据在写入时要先进行寻址操作,该操作是通过移动磁头完成的,避免该操作
- 零拷贝
- 普通的数据拷贝流程如图所示,数据由磁盘copy到内核态,然后再拷贝到用户态,然后再用户态拷贝到socket,然后由socket协议引擎,最后由协议引擎将数据发送到网络中
- 采取零拷贝技术,数据不再经过用户态传输,而是直接在内核态完成操作,减少了两次copy操作
- 普通的数据拷贝流程如图所示,数据由磁盘copy到内核态,然后再拷贝到用户态,然后再用户态拷贝到socket,然后由socket协议引擎,最后由协议引擎将数据发送到网络中
- 文件分段
- 批量发送
- 数据压缩
- 顺序读写
- 高可用性