赞
踩
是一个分布式、支持分区的(partition)、多副本的(replica)得消息中间件。
运维难度大,对带宽有一定要求。
Producer:Producer即生产者,消息的产生者,是消息的入口。
Consumer:消费者,即消息的消费方,是消息的出口。
Broker:Broker是kafka实例,每个服务器上有一个或多个kafka的实例,我们姑且认为每个broker对应一台服务器。每个kafka集群内的broker都有一个不重复的编号,如图中的broker-0、broker-1等……
Topic:逻辑概念;消息的主题,可以理解为消息的分类,kafka的数据就保存在topic。在每个broker上都可以创建多个topic。
Partition:Topic的分区,每个topic可以有多个分区,分区的作用是做负载,提高kafka的吞吐量。同一个topic在不同的分区的数据是不重复的,partition的表现形式就是一个一个的文件夹!kafka得partition局部有序。
Replication:每一个分区都有多个副本,副本的作用是做备份,保证高可用。当主分区(Leader)故障的时候会选择一个备胎(Follower)上位,成为Leader。在kafka中默认副本的最大数量是10个,且副本的数量不能大于Broker的数量,follower和leader绝对是在不同的机器,同一机器对同一个分区也只可能存放一个副本(包括自己)。
Message:每一条发送的消息主体。
Consumer Group:我们可以将多个消费组组成一个消费者组,在kafka的设计中同一个分区的数据只能被消费者组中的某一个消费者消费。同一个消费者组的消费者可以消费同一个topic的不同分区的数据,这也是为了提高kafka的吞吐量!
Zookeeper:kafka集群依赖zookeeper来保存集群的的元信息,来保证系统的可用性。
简单介绍:
1. 生产端会在集群里面获取broker中partition所有信息,获取到ISR集合,从其中找到leader节点。(写得时候是push)
2.生产端讲消息发送给leader
3.leader将消息写入本地文件中,主写(es中也是主写,zk中也是主写)
4.follower从leader中pull消息(follower同步消息也是通过pull拉取消息)
5.follower写完将消息写入本地向leader发送ack。(当follower太多场景下,这块也会有性能问题,通常为了保证生产端消息不丢失会开启ack机制,当配置ack为-1,所有follower都会写文件,这也是kafka得缺点之一,需要一定得带宽,否则消息处理也很慢)
6.leader收到所有副本消息向prouder发送ack
备注:kafka中partition就是一个文件,文件中具有segment(这一点和es文件有相似指出);
具体日志文件有.index和.log文件
.index索引文件:
里面使用了稀疏索引,为什么使用稀疏索引原因?在我看来,为了节省空间,比如存储一个offset成本相对比较高,而使用当前index前缀+偏移量会省很大得空间。具体存储内容:偏移量索引+具体数据偏移量。
消息存储在log文件后,消费者就可以进行消费了。在讲消息队列通信的两种模式的时候讲到过点对点模式和发布订阅模式。Kafka采用的是发布订阅模式,消费者主动的去kafka集群拉取消息,与producer相同的是,消费者在拉取消息的时候也是找leader去拉取。
多个消费者可以组成一个消费者组(consumer group),每个消费者组都有一个组id!同一个消费组者的消费者可以消费同一topic下不同分区的数据,但是不会组内多个消费者消费同一分区的数
利用segment+有序offset+稀疏索引+二分查找+顺序查找
利用consumer group进行实现,会给每一个分配一个groupId。
1.批量发送数据+压缩机制
2.kafka零拷贝
3.顺序写
4.页缓存技术
ISR
如果一台follower因为某种原因迟迟不能同步数据,那么leader就需要一直等它而不能发送ack,为了解决这个问题,kafka采用了一个ISR方案。
leader维护了一个动态的in-sync-replica (与leader保持同步的副本集合,该集合中的副本和leader数据是一致的),当isr中的follower和leader数据同步完成之后,leader就会向follower发送ack,如果isr中的follower长时间未向leader发送同步完成消息,leader会将其从isr中剔除,等待的时长由replica.time.max.ms参数设定。leader故障之后,就会从ISR中选举出新的leader。
0:producer不等待broker的ack,这种方式提供了一个最低的延迟,broker一接收到还没写入磁盘就已经返回,当broker故障时可能存在数据丢失。
1:producer等待broker的ack,partition的leader落盘成功后返回ack,如果follower同步成功之前leader故障,存在数据丢失。
-1: producer等待leader、follower全部落盘成功后返回ack,这种情况不存在数据丢失,但是,如果落盘成功后,leader故障还未来得及向producer发送ack,producer认为失败了会重新发送消息。就会造成数据重复。
要实现数据不重复,保证exactly-once,kafka需要进行重复判断(幂等),如果已经有该条offset数据就不重新写入了。
高水位和低水位
(1)follower故障
follower故障后会被leader踢出ISR,follower故障恢复时,需要恢复到和leader数据保持一致,follower会读取本地磁盘上次记录的HW并截取掉高于HW的offset消息,高于HW的消息重新冲leader同步获取。等follower的LEO大于等于该partition的HW,即follower追上leader后,重新加入到ISR中。
leader HW 和 LEO之间的数据对consumer是不可见的,因为follower数据还没有同步完成。
因此如果一个被剔除出ISR的follower需要恢复,重新加入到ISR中,它需要从它记录的上次HW开始同步leader数据,如果它上次记录的HW和LEO之间还有数据,这部分数据不是有效要丢掉,重新从leader同步,知道它的LEO追上现在leader的HW才能加入到ISR集合中
(2)leader故障
leader故障后,从ISR中重新选出一个新的leader,之后,为保证多个副本之间的数据一致性,其余的follower会现将各自的log文件高于HW的部分截掉,然后从新的leader同步数据
注意:只能保证副本之间数据的一致性,并不能保证数据不丢失或者数据不重复。
一共进行了4次拷贝,3,5,8,10操作
一共进行了4次上下文切换,1,6,7,12操作
mmap是linux得设计,省去了调用了read得操作
拷贝次数3次,3,7,9
cpu上下文4次,1,5,6,11
sendfile()
拷贝过程3次,3,5,7;只是减少了用户态得拷贝
cpu切换:1,9;减少了2次切换
transferForm()调用了sendFile()
答案:会丢失数据
原因:生产者会把发送到同一个 partition 的多条消息,封装在一个 batch(缓冲区)中。当 batch 满了(参数 batch.size 默认16kb),或者消息达到了超时时间(参数 linger.ms),缓冲区中的消息就会被发送到 broker 上。
这个缓冲区默认是 16KB,如果生产者的业务突然断电,这 16KB 数据是没有机会发送出去的。此时,就造成了消息丢失。
解决的办法有两种:
这同样和生产者的缓冲区有关。缓冲区大小毕竟是有限制的,如果消息产生得过快,或者生产者与 broker 节点之间有网络问题,缓冲区就会一直处于 full 的状态。此时,有新的消息到达,会如何处理呢?
通过配置生产者的超时参数和重试次数,可以让新的消息一直阻塞在业务方。一般来说,这个超时值设置成 1 秒就已经够大了,有的应用在线上把超时参数配置得非常大,比如 1 分钟,就造成了用户的线程迅速占满,整个业务不能再接受新的请求。
之前的版本是存储在zookeeper中,后期版本存入kafka中,因为频繁的写入对zk性能有影响。
kafka中内置一个commer_offset,结构是 key,value类型的
key代表:消费者组id+topic+partition,value代表偏移量
早期版本中zookeeper在kafka中作用?
1.协调和领导者选举
Zookeeper协助Kafka集群中的各个Broker选举一个领导者(Leader)。这个领导者负责管理分区的写入和读取请求,并协调分布式的事务。如果领导者发生故障,Zookeeper会帮助选举一个新的领导者。通过ISR集合
2.分区分配(rebalnce):当新的消费者加入或现有消费者离开Kafka集群时,Zookeeper协助进行分区分配,确保每个消费者获得它们要订阅的分区。
3.配置管理:Kafka的一些配置参数和元数据信息(如分区和副本的状态)也存储在Zookeeper中,以供Kafka集群中的各个Broker和消费者使用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。