Kafka工作原理

kafka是一个以日志形式存储消息的消息中间件,以高吞吐而闻名。

一、生产者producer

1.ack模式

    前提:kafka的服务器broker是个集群

1.1 ack = 0

    生产者只管投递,并不关注kafka服务器broker是否接收到消息。

    缺点:可能会出现消息丢失。

1.2 ack = 1

    生产者投递消息后,broker副本的leader接收到消息,在本地持久化后,就返回生产者消息发送成功;然后开启线程向其它follower同步这条消息。

    缺点:leader在ack后,还未来得及将消息同步给follower就宕机了,kafka集群新的leader并没这条消息,原leader启动后,由于高水位线机制(下文会讲到),也不会有这条消息,该消息丢失。

    解决方法:建立一张本地消息表,生产者发送消息前,将消息先写入本地。

1.3 ack = -1

    生产者投递消息后,broker副本的leader接收消息后,将消息同步给整个副本集群后,在返回给生产者。

    缺点:耗时久;leader将数据都同步给副本集群后,在ack过程中宕机;生产者会以为出现错误而重试,导致新leader上重复接收了这条消息。

2.批量发送

    kafka发送消息不会一条一条发送,而是有一个缓冲区,当缓冲区满了,生产者会批量将这些消息发送到broker,减少IO通讯次数。也会通过定时任务定时发送缓冲区的消息。

3.消息压缩

    发送消息时会将消息进行压缩(去掉注释,空格等信息),降低带宽。

4.零拷贝(linux的api)

    采用dma拷贝代替cpu拷贝,降低cpu压力。

    同时使用mmap内存映射,使用户空间和内核空间进行内存共享,减少用户态和内核态的切换次数。

    使用sendfile将mmap中的数据直接发送到网卡传输。

    整个过程cpu切换两次,cpu拷贝0次。

二、消息服务器

1. broker

    kafka的物理服务器,用于保存和转发消息。

2.topic

    逻辑概念,消息的一种类型,或者说消息的一种属性。

3.partition

    topic的物理存储概念,也是topic在broker中的具体存放空间。

    以segment格式存放(类似于ConcurrentHashMap7的原理,分摊治理),当单个segment文件的大小超过500M(默认配置)时,会自动生成下一个Segment,文件以上一个segment的最大offset命名,长度20位,不足补零。

    segment中由.index和.log组成。.index为offset的稀疏索引,key为offset,value为地址指针;.log为实际存放消息的文件,key为地址指针,value为消息体。

4.zookeeper

    kafka的注册中心,存储broker、topic、partition、group等信息。

5.controller

    管理副本选举以及topic分配等操作,通过分布式锁的方式创建。(多个broker去zk上创建相同的临时节点,谁创建成功谁就是controller,其余broker订阅该节点,当controller宕机后,zk会自动删除,发送事件通知这些broker重新竞争)。

6.副本

    集群模式下,为了高可用,数据会在多个broker上存在多份,也就是副本。controller会通过broker与zk的链接而保存一个副本的集合,即ISR。

    副本leader就是ISR的第一个节点,当leader宕机后,zk与其断开链接,controller将其从ISR头部剔除,新的leader就是ISR的新头部,原leader恢复后,与ZK保持通讯,controller将其重新加入ISR,放入集合末尾。

    每个副本都有两个参数:LEO和HW。LEO表示当前副本中存放的最大的offset值,HW则表示消费者可以看到的最大offset值(即所有副本交集中最大的offset),当副本数据同步时,follower副本会舍弃高于HW的offset的消息,重新去leader同步消息,所以可能会 出现消息丢失。

三、消费者consumer

1.consumer

    消费者节点,订阅partition,根据offset从partition上取数据,当消费成功后,会commit offset至partition,partition通过定时任务删除这些已消费的数据。

2.group

    消费组,将消费者分类,同一个消费组中的消费者消费同一个partition的相同消息,commit offset时会有问题。

3.消费记录

    topic的日志文件中会消费者在分区中的消费记录,默认分成50个文件,来通过key(key=group-id.topic.partition)取模的方式,找到文件查询消费记录,进而消费下一个offset。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>