一:先来了解下概念
Kafka 是一种高吞吐量、散布式、根据发布/订阅的音讯体系,最初由 LinkedIn 公司开发,运用 Scala 语言编写,目前是 Apache 的开源项目,也是目前较为干流的音讯列队。作用吗和其他音讯行列相识,主要用于 【异步】,【解耦】,【削峰】。
二:Kafka组成
- Producer: 音讯出产者,向 Kafka Broker 发音讯的客户端。
- Consumer: 音讯顾客,从 Kafka Broker 取音讯的客户端。
- Consumer Group: 顾客组(CG),顾客组内每个顾客负责消费不同分区的数据,进步消费才能。一个分区只能由组内一个顾客消费,顾客组之间互不影响。一切的顾客都归于某个顾客组,即顾客组是逻辑上的一个订阅者。
- Broker: 一台 Kafka 机器便是一个 broker。一个集群由多个 broker 组成。一个 broker 能够包容多个 topic。
- Topic: 能够理解为一个行列,topic 将音讯分类,出产者和顾客面向的是同一个 topic。
- Partition: 为了完结扩展性,进步并发才能,一个非常大的 topic 能够散布到多个 broker (即服务器)上,一个 topic 能够分为多个 partition,每个 partition 是一个 有序的行列。
- Replica: 副本,为完结备份的功用,保证集群中的某个节点发生毛病时,该节点上的 partition 数据不丢掉,且 Kafka 依然能够持续作业,Kafka 供给了副本机制,一个 topic 的每个分区都有若干个副本,一个 leader 和若干个 follower。
- Leader: 每个分区多个副本的“主”副本,出产者发送数据的目标,以及顾客消费数据的目标,都是 leader。
- Follower: 每个分区多个副本的“从”副本,实时从 leader 中同步数据,坚持和 leader 数据的同步。leader 发生毛病时,某个 follower 还会成为新的 leader。
- offset: 顾客消费的方位信息,监控数据消费到什么方位,当顾客挂掉再从头康复的时分,能够从消费方位持续消费。
- Zookeeper: Kafka 集群能够正常作业,需求依赖于 zookeeper,zookeeper 协助 Kafka 存储和管理集群信息
三:Kafka 数据存储规划
3.1. partition 的数据文件(offset,MessageSize,data)
partition 中的每条 Message 包含了以下三个特点:offset,MessageSize,data,其间 offset 表 示 Message 在这个 partition 中的偏移量,offset 不是该 Message 在 partition 数据文件中的实 13/04/2018 Page 176 of 283 际存储方位,而是逻辑上一个值,它仅有承认了 partition 中的一条 Message,能够以为 offset 是 partition 中 Message 的 id;MessageSize 表明音讯内容 data 的巨细;data 为 Message 的具 体内容。
3.2 数据文件分段 segment(次序读写、分段指令、二分查找)
partition 物理上由多个 segment 文件组成,每个 segment 巨细持平,次序读写。每个 segment 数据文件以该段中最小的 offset 命名,文件扩展名为.log。这样在查找指定 offset 的 Message 的 时分,用二分查找就能够定位到该 Message 在哪个 segment 数据文件中。
3.3 数据文件索引(分段索引、稀少存储)
Kafka 为每个分段后的数据文件建立了索引文件,文件名与数据文件的姓名是相同的,仅仅文件扩 展名为.index。index 文件中并没有为数据文件中的每条 Message 建立索引,而是选用了稀少存 储的方法,每隔必定字节的数据建立一条索引。这样防止了索引文件占用过多的空间,然后能够 将索引文件保留在内存中。
四:出产者规划
4.1 负载均衡(partition 会均衡散布到不同 broker 上)
由于音讯 topic 由多个 partition 组成,且 partition 会均衡散布到不同 broker 上,因而,为了有 效运用 broker 集群的功用,进步音讯的吞吐量,producer 能够经过随机或者 hash 等方法,将消 息平均发送到多个 partition 上,以完结负载均衡。
4.2 批量发送
是进步音讯吞吐量重要的方法,Producer 端能够在内存中兼并多条音讯后,以一次恳求的方法发 送了批量的音讯给 broker,然后大大削减 broker 存储音讯的 IO 操作次数。但也必定程度上影响 了音讯的实时性,相当于以时延价值,换取更好的吞吐量。
4.3 紧缩(GZIP 或 Snappy)
Producer 端能够经过 GZIP 或 Snappy 格式对音讯调集进行紧缩。Producer 端进行紧缩之后,在 Consumer 端需进行解压。紧缩的优点便是削减传输的数据量,减轻对网络传输的压力,在对大 数据处理上,瓶颈往往表现在网络上而不是 CPU(紧缩和解压会耗掉部分 CPU 资源)。
五:顾客规划
5.1 Consumer Group
同一 Consumer Group 中的多个 Consumer 实例,不一起消费同一个 partition,等效于行列模 式。partition 内音讯是有序的,Consumer 经过 pull 方法消费音讯。Kafka 不删去已消费的音讯 关于 partition,次序读写磁盘数据,以时刻复杂度 O(1)方法供给音讯耐久化才能。
六:数据可靠性
6.1 ack机制
为保证producer 发送的数据不丢掉,broker 接收到数据后都需求对producer发送ack(承认接收) ,假如producer 未收到ack则会从头发送该条音讯。producer 的 ack 战略又分为三种:
- ack=0 producer不等候broker同步完结的承认,持续发送下一条(批)信息
- ack=1 producer要等候leader成功收到数据并得到承认,才发送下一条message。
- ack=-1 producer得到follwer承认(全副本同步完结),才发送下一条数据
6.2 ISR (同步副本表)
选用全副本同步完结再ack会有一个问题:
当leader 接收完数据,一切的follower开始同步数据,但一旦有一个follower不能与leader进行同步,那leader会一向等下去,这样会非常的浪费时刻。
为此kafka引入了 isr 机制——leader会保护一个动态的 isr(in-sync replica set)列表,这个列表保护了和leader坚持同步的调集。当ISR中的follower完结数据的同步之后,leader就会发送ack。假如follower 长时刻未向leader同步数据,则该follower将会被踢出 isr,当其他满意条件的follower也会被加入到isr。这个同步最大时刻装备项为replica.lag.time.max.ms
参数设置。假如leader毛病了,也会从isr的follower中推举新的leader。
6.3 数据一致性处理
由于副本的音讯数在各个之间是存在差异的,或许leader10条,而follower只同步了8条;当leader挂掉,数据就有或许会发生丢掉,经过一种机制来保证顾客消费数据的一致性就很有必要了。kafka的数据一致性经过 LEO(每个副本的最终一条offset)和HW(一切的LEO中最小的那个)来保证。示意图:
顾客只能看到offset<=HW 的音讯。
七:消费机制
7.1 消费战略
kafka 对音讯消费的处理有三种方法:
- (at least once)至少一次
- (at most once)至多一次
- (exactly once) 有且只要一次
由于ack机制的存在,producer 向kafka发送音讯时假如 ack=0,由于producer不等承认音讯是否投递成功就不管了 ,或许丢掉数据,此刻顾客最多消费一次音讯;假如ack=1,当producer未收到音讯承认投递成功时会再次投递,这个时分或许音讯被投递了多次,或许会存在重复消费的状况。当kafka敞开数据幂等性且ack=1的时分,此刻重复的音讯会被去重,因而不会发生重复消费的状况。
启用幂等性的方法是将producer中的参数enable.idompotence
设置为true。
7.2 顾客相关特性
和rabbitMQ相同,能够指定顾客消费音讯是推方法仍是拉方法。在顾客组中,有多个顾客,一个topic中有多个partition。那么音讯的分配是怎么样的呢,首先一个顾客组中的顾客不能一起消费同一个partition,这是根本原则。 然后partiotion的分配机制有两种,一种是range(规模) 一种是 RoundRobin(轮询),range示 意图:
RoundRobin 示意图:
由于consumer也或许会宕机挂掉的风险,当consumer康复的时分有必要要能够从上一次消费的当地从头开始消费。所以consumer需求实时记载自己消费到了哪一个offset,以便能够康复到宕机前状况。
八:一些疑问
8.1 kafka高效读写保证
kafka的producer出产数据,要以追加的方法写入到log文件中,这个写磁盘的进程是次序写,相关于磁盘的随机写来说,这个效率要高出许多,这个是kafka高效读写的保证之一。而别的的一个保证高效读写的技能是零仿制,用过netty的同学应该知道这个,中间少了两次用户态的切换。
8.2 Kafka无丢掉音讯处理方案
完结Kafka无丢掉音讯的处理方案如下:
- 有必要运用producer.send(msg, callback)接口发送音讯。
- Producer端设置acks参数值为all。acks参数值为all表明ISR中一切Broker副本都接收到音讯,音讯才算已提交。
- 设置Producer端retries参数值为一个较大值,表明Producer自动重试次数。当呈现网络瞬时抖动时,音讯发送或许会失利,此刻Producer能够自动重试音讯发送,防止音讯丢掉。
- 设置Broker端unclean.leader.election.enable = false,unclean.leader.election.enable参数用于控制有资历竞选分区Leader的Broker。假如一个Broker落后原Leader太多,那么成为新Leader必然会形成音讯丢掉。因而,要将unclean.leader.election.enable参数设置成false。
- 设置Broker端参数replication.factor >= 3,将音讯保存多份副本。
- 设置Broker参数min.insync.replicas > 1,保证ISR中Broker副本的最少个数,在acks=-1时才收效。设置成大于1能够提高音讯耐久性,出产环境中不能运用默许值 1。
- 有必要保证replication.factor > min.insync.replicas,假如两者持平,那么只要有一个副本挂机,整个分区无法正常作业。引荐设置成replication.factor = min.insync.replicas + 1。
- 保证音讯消费完结再提交。设置Consumer端参数enable.auto.commit为false,并选用手动提交位移的方法。
可是上边的一些操作很大一部分限制了kafka 本身的吞吐量。
8.3 Kafka音讯重复消费问题
8.3.1 顾客消费进程解析
出产者将音讯发送到Topic中,顾客即可对其进行消费,其消费进程如下:
- Consumer向Broker提交衔接恳求,其所衔接上的Broker都会向其发送Broker Controller的通信URL,即装备文件中的listeners地址;
- 当Consumer指定了要消费的Topic后,会向Broker Controller发送消费恳求;
- Broker Controller会为Consumer分配一个或几个Partition Leader,并将Partition的当时offset发送给Consumer;
- Consumer会按照Broker Controller分配的Partition对其间的音讯进行消费;
- 当Consumer消费完音讯后,Consumer会向Broker发送一个音讯现已被消费反馈,即音讯的offset;
- 在Broker接收到Consumer的offset后,会更新相应的consumer_offset中;
- Consumer能够重置offset,然后能够灵活消费存储在Broker上的音讯。
8.3.2 重复消费处理方案
1.0 同一个Consumer重复消费
当Consumer由于消费才能低而引发了消费超时,则或许会形成重复消费。 在某数据刚好消费结束,但正准备提交offset时,消费时刻超时,则Broker以为音讯未消费成功,发生重复消费问题。
2.0 其处理方案:延伸offset提交时刻。
不同的Consumer重复消费 当Consumer消费了音讯,但还没有提交offset时宕机,则现已被消费过的音讯会被重复消费。 其处理方案:将自动提交改为手动提交
从架构规划上处理Kafka重复消费的问题
- 保存并查询
- 给每个音讯都设置一个仅有的UUID,在消费音讯时,首先去耐久化体系中查询,查看音讯是否被消费过,假如没有消费过,再进行消费;假如现已消费过,直接丢弃。
- 运用幂等性
- 幂等性操作的特点是任意多次履行所发生的影响均与一次履行的影响相同。 假如将体系消费音讯的业务逻辑规划为幂等性操作,就不用忧虑Kafka音讯的重复消费问题,因而能够将消费的业务逻辑规划成具备幂等性的操作。运用数据库的仅有束缚能够完结幂等性,如在数据库中建一张表,将表的两个或多个字段联合起来创立一个仅有束缚,因而只能存在一条记载。
- 设置前提条件
- 完结幂等性的另一种方法是给数据改变设置一个前置条件。假如满意条件就更新数据,否则回绝更新数据,在更新数据的时分,一起改变前置条件中需求判断的数据。
8.3.3 kafka为什么这么快
- 运用 Partition 完结并行处理 :我们都知道 Kafka 是一个 Pub-Sub 的音讯体系,无论是发布仍是订阅,都要指定 Topic。Topic 仅仅一个逻辑的概念。每个 Topic 都包含一个或多个 Partition,不同 Partition 可坐落不同节点。
- 次序读写:由于硬盘是机械结构,每次读写都会寻址->写入,其间寻址是一个“机械动作”,它是最耗时的。所以硬盘最“厌烦”随机I/O,最喜欢次序I/O。为了进步读写硬盘的速度,Kafka便是运用次序I/O。
- 充分运用 Page Cache:引入 Cache 层的意图是为了进步 Linux 操作体系对磁盘访问的功用。Cache 层在内存中缓存了磁盘上的部分数据。当数据的恳求到达时,假如在 Cache 中存在该数据且是最新的,则直接将数据传递给用户程序,免除了对底层磁盘的操作,进步了功用。Cache 层也正是磁盘 IOPS 为什么能打破 200 的主要原因之一。在 Linux 的完结中,文件 Cache 分为两个层面,一是 Page Cache,另一个 Buffer Cache,每一个 Page Cache 包含若干 Buffer Cache。Page Cache 主要用来作为文件体系上的文件数据的缓存来用,尤其是针对当进程对文件有 read/write 操作的时分。Buffer Cache 则主要是规划用来在体系对块设备进行读写的时分,对块进行数据缓存的体系来运用。
-
零仿制技能:
- 零仿制(Zero-copy)技能指在核算机履行操作时,CPU 不需求先将数据从一个内存区域仿制到另一个内存区域,然后能够削减上下文切换以及 CPU 的仿制时刻。它的作用是在数据报从网络设备到用户程序空间传递的进程中,削减数据仿制次数,削减体系调用,完结 CPU 的零参与,彻底消除 CPU 在这方面的负载。
- mmap:Memory Mapped Files:简称 mmap,也有叫 MMFile 的,运用 mmap 的意图是将内核中读缓冲区(read buffer)的地址与用户空间的缓冲区(user buffer)进行映射。然后完结内核缓冲区与应用程序内存的同享,省去了将数据从内核读缓冲区(read buffer)仿制到用户缓冲区(user buffer)的进程。它的作业原理是直接运用操作体系的 Page 来完结文件到物理内存的直接映射。完结映射之后你对物理内存的操作会被同步到硬盘上。运用这种方法能够获取很大的 I/O 提高,省去了用户空间到内核空间仿制的开支。
- 批处理:在许多状况下,体系的瓶颈不是 CPU 或磁盘,而是网络IO。因而,除了操作体系供给的初级批处理之外,Kafka 的客户端和 broker 还会在经过网络发送数据之前,在一个批处理中累积多条记载 (包含读和写)。记载的批处理分摊了网络往复的开支,运用了更大的数据包然后进步了带宽运用率。
- 数据紧缩:Producer 可将数据紧缩后发送给 broker,然后削减网络传输价值,目前支撑的紧缩算法有:Snappy、Gzip、LZ4。数据紧缩一般都是和批处理配套运用来作为优化手段的。
总结:
- 1.0 partition 并行处理
- 2.0 次序写磁盘,充分运用磁盘特性
- 3.0 运用了现代操作体系分页存储 Page Cache 来运用内存进步 I/O 效率
- 4.0 选用了零仿制技能
- 5.0 Producer 出产的数据耐久化到 broker,选用 mmap 文件映射,完结次序的快速写入
- 6.0 Customer 从 broker 读取数据,选用 sendfile,将磁盘文件读到 OS 内核缓冲区后,转到 NIO buffer进行网络发送,削减 CPU 消耗
8.3.4 Kafka中的HW、LEO、LSO、LW等别离代表什么?
- HW是High Watermak的缩写,俗称高水位,它表明了一个特定音讯的偏移量(offset),消费之只能拉取到这个offset之前的音讯。
- LEO是Log End Offset的缩写,它表明了当时日志文件中下一条待写入音讯的offset。
- LSO特指LastStableOffset。它详细与kafka的事物有关。消费端参数——isolation.level,这个参数用来装备顾客业务的阻隔等级。字符串类型,“read_uncommitted”和“read_committed”。
- LW是Low Watermark的缩写,俗称“低水位”,代表AR调集中最小的logStartOffset值,副本的拉取恳求(FetchRequest)和删去恳求(DeleteRecordRequest)都或许促使LW的增长。
8.3.5 Kafka中是怎么表现音讯次序性的
- 一个 topic,一个 partition,一个 consumer,内部单线程消费,单线程吞吐量太低,一般不会用这个。
- 写 N 个内存 queue,具有相同 key 的数据都到同一个内存 queue;然后关于 N 个线程,每个线程别离消费一个内存 queue 即可,这样就能保证次序性。
8.3.6 Kafka中的ISR、AR又代表什么?ISR的伸缩又指什么?
- 分区中的一切副本统称为AR(Assigned Repllicas)。一切与leader副本坚持必定程度同步的副本(包含Leader)组成ISR(In-Sync Replicas),ISR调集是AR调集中的一个子集。与leader副本同步滞后过多的副本(不包含leader)副本,组成OSR(Out-Sync Relipcas),由此可见:AR=ISR+OSR。
- ISR调集的副本有必要满意: 副本地点节点有必要维持着与zookeeper的衔接;副本最终一条音讯的offset与leader副本最终一条音讯的offset之间的差值不能超出指定的阈值
- 每个分区的leader副本都会保护此分区的ISR调集,写恳求首先由leader副本处理,之后follower副本会从leader副本上拉取写入的音讯,这个进程会有必定的推迟,导致follower副本中保存的音讯略少于leader副本,只要未超出阈值都是能够忍受的
- ISR的伸缩指的是Kafka在发动的时分会敞开两个与ISR相关的守时使命,名称别离为“isr-expiration”和”isr-change-propagation”.。isr-expiration使命会周期性的检测每个分区是否需求缩减其ISR调集。
8.3.6 假如我指定了一个offset,Kafka怎么查找到对应的音讯?
- 经过文件名前缀数字x找到该肯定offset 对应音讯地点文件。
- offset-x为在文件中的相对偏移。
- 经过index文件中记载的索引找到最近的音讯的方位。
- 从最近方位开始逐条寻找。
8.3.7 Kafka中的推迟行列怎么完结?
Kafka中存在大量的推迟操作,比如推迟出产、推迟拉取以及推迟删去等。Kafka并没有运用JDK自带的Timer或者DelayQueue来完结推迟的功用,而是根据时刻轮自定义了一个用于完结推迟功用的守时器(SystemTimer)。JDK的Timer和DelayQueue插入和删去操作的平均时刻复杂度为O(nlog(n)),并不能满意Kafka的高功用要求,而根据时刻轮能够将插入和删去操作的时刻复杂度都降为O(1)。Kafka中的时刻轮(TimingWheel)是一个存储守时使命的环形行列,底层选用数组完结,数组中的每个元素能够寄存一个守时使命列表(TimerTaskList)。TimerTaskList是一个环形的双向链表,链表中的每一项表明的都是守时使命项(TimerTaskEntry),其间封装了真正的守时使命TimerTask。时刻轮由多个时刻格组成,每个时刻格代表当时时刻轮的根本时刻跨度(tickMs)。时刻轮的时刻格个数是固定的,可用wheelSize来表明,那么整个时刻轮的总体时刻跨度(interval)能够经过公式 tickMs wheelSize核算得出。
8.3.8 顾客提交消费位移时提交的是当时消费到的最新音讯的offset仍是offset+1?
offset+1
8.3.9 优先副本是什么?它有什么特别的作用?
优先副本 会是默许的leader副本 发生leader变化时重推举会优先选择优先副本作为leader
本文正在参与「金石计划」