赞
踩
Kafka 是一个分布式流式处理平台。LinkedIn 最早开发 Kafka 用于处理海量的日志有很大关系,最开始就不是为了作为消息队列的,由于高性能,以及随着发展很多短板都被逐步修复完善,后面才在消息队列领域占据了一席之地。
主要有两大应用场景:
Kafka使用 Zookeeper保存Broker集群的元数据信息,主要包括Broker和Topic的元数据信息,老版的Kafka的消费者信息也是使用Zookeeper进行存储,新版则使用Broker存储消费者信息。
在创建Topic时,通过指定分区的个数(num.patitions),kafka会根据一定的策略将分区分配在不同broker上来保证高吞吐,同时每个分区又可以根据复制系数(replicatlon.factor)分配多个副本到不同broker上,保证消息的可靠性。副本类型分为首领副本和跟随者副本,除了首领副本,其余都叫跟随者副本,首领副本会和跟随者副本之间进行数据同步。首领副本负责消息的写入和读取,首领副本所在的broker宕机之后,控制器会选择一个跟随者副本成为新的首领副本。控制器其实就是一个 broker,只不过它除了具有一般 broker 的功能之外,还负责分区首领的选举。
假设你有 6个 broker,打算创建一个包含 10个分区的主题,并且复制系数为 3。那么 Kafka就会有 30个分区副本, 它们可以被分配给 6个 broker。在进行分区分配时,我们从分区首领开始,依次分配跟随者副本。如果分区0的首领在broker4上,那么它的第一个跟随者副本会在 broker 5 上,第二个跟随者副本会在 broker 0上。分区1的首领在broker5上,那么它的第一个跟随者副本在 broker0上,第二个跟随者副本在 broker1上。
获取元数据信息
生产者需要获取到topic的元数据,topic有哪些分区,分区leader在哪几台broker上,broker的ip.port等,生产者可以请求任一broker获取这些元数据信息,因为所有 broker都缓存了这些信息。
消息分发策略
一条消息由key和value两部份构成,但key是可选的,如果指定了key,那么producer会根据key和partition机制(hash取模)来判断当前这条消息应该存储到哪个partition中。未指定key,则随机选择一个partition存储。
1.一个分区只会分配给一个Consumer(同RocketMQ)。[想并发高就用多个队列,而不是多个消费者消费一个队列]
2.消费者负载均衡:在集群环境下,partition会被均匀分布在各个节点中,并且每一个topic会有多个consumer来订阅消费消费,而每个consumer在向broker请求消息时,会分配一个专属的partition给到consumer,这样当多个consumer向某个topic消费消息时,broker会将请求分发到存储partition的各个节点上。这种设计即是消费端的负载均衡机制。
3.分区分配策略:
触发条件
Coordinator角色
是kafka集群中的一个节点,每个consumer group都有一个Coordinator来管理以及协调成员消息消费,该角色负责consumer leader选举、consumer的分区派发、rebalance。
确定coordinator角色
当consumer group中的第一个consumer启动的时候,它会去和kafka server确定谁是它们组的coordinator,broker会返回一个负载最小的节点id,并将该broker设置为该group的coordinator,之后该group内所有consumer都和该coordinator进行通信。
Rebanlance
在rebalance之前,需要保证consumer group确定了coordinator。整个rebalance过程分为 Join(Join Group) 和 Sync(Synchronizing Group State) 两个阶段:
Kafka 只能为我们保证 Partition(分区) 中的消息有序。每个消息被添加到分区时,会分配一个offset(偏移量,从0开始编号),是消息在一个分区中的唯一编号,kafka可通过offset保证消息在同一个分区的顺序
发送者丢失:1同步发送结果;或 2设置回调重试
接收者丢失:提交offset后处理消息挂了导致消息重复消费;处理后提交offset时挂了又会导致重复消费
1.每个生产者有一个sequenceID,broker会记录每个producer对应的当前最大sequence,如果新的消息带上的sequence不大于当前的最大sequence就拒绝这条消息,如果消息落盘会同时更新最大sequence,这个时候重发的消息会被服务端拒掉从而避免消息重复。
2.消费者保证幂等。
不同于rocketmq的事物(保证本地执行+发消息是一个事务),kafka的事物类似数据库(保证发送多个消息到不同主题分片是一个事务,也有事务隔离级别配置-消费者RU/RC)
削峰 ——如果这个峰值太大了会导致大量消息堆积在队列,原因主要有二:生产者生产太快或者消费者消费太慢。
Producer使用push模式将消息推送到Broker的某个Topic,Consumer通过监听topic使用pull模式从Broker拉取消息。
(同rocketmq消费者pull是为了避免push可能造成消费者处理不过来)
1.批量+压缩:
kafka的生产者在消息发送的时候,可以根据分批大小和分批等待时间,对消息进行批量发送,同时会使用相应的压缩算法(snappy、gzip)对消息进行压缩(增加了消息延迟时间,可以关掉)
2.顺序读写:
kafka中对于每个分区的消息都是顺序写入和顺序读取的,这样可以提高磁盘的读写速度
3.零拷贝技术:
kafka默认使用sendfile技术来实现消息的读取和写入,sendfile相对于mmap不仅可以减少拷贝次数,还可以减少上下文切换的次数。
4.索引文件:
kafka的文件存储形式包含了日志文件和索引文件,索引文件可以有效提高消息的读取速度
1.副本同步原理
2.Leader副本的选举过程
KafkaController会监听ZooKeeper的/brokers/ids节点路径,一旦发现有broker挂了,在该broker上的leader分区会重新选举leader(KafkaController挂了,各个broker会重新leader选举出新的KafkaController)
1.acks
acks参数指定了必须要有多少个分区副本收到消息,生产者才会认为消息写入是成功的。这个参数对消息丢失的可能性有重要影响。
1)ack=0,生产者在成功写入悄息之前不会等待任何来自服务器的响应。
2)ack=1,只要集群的首领副本收到消息,生产者就会收到一个来自服务器的成功响应。
3)ack=all或-1,只有当所有同步副本全部收到消息时,生产者才会收到一个来自 服务器的成功响应。
2.不完全首领选举:
不完全首领选择是指是否允许不同步副本选举称为首领副本,10s内没有请求首领副本最新消息的跟随者副本被称之为不同步副本。如果我们允许不同步的副本成为首领,那么就要承担丢失数据和出现数据不一致的风险。 如果不允许它们成为首领,那么就要接受较低的可用性,因为我们必须等待原先的首领恢复到可用状态 。通过unclean.leade.election.enable参数设置不完全首领选举是否开启
3.最小同步副本:
通过min.insync.replicas参数设置最小同步副本个数。例如包含3个副本的主题,如果 min.insync.replicas被设为 2,那么至少要存在两个同步副本才能向leader分区写入数据。
4.同步异步刷盘:
同步异步刷盘的区别在于,消息存储在内存中以后,是否会等待执行完刷盘动作再返回。kafka可以通过配置flush.message和flush.ms来设置刷盘策略,如果flush.message设置为5,表示每5条消息进行一次刷盘。如果flush.ms设置为1000,表示每过1000ms进行一次刷盘。
5.什么情况会丢失信息?
acks=0、1:Leader副本接收成功后挂掉,而Follower副本可能还在同步,新Leader副本(原Follower副本)未能和其保持一致,就会出现消息丢失的情况。
acks=-1但isr列表为空:所有的Replia都不工作,等待Replica唤醒期间的消息都会丢失。
1.组成:每个分区会创建一个分区目录,分区目录下面存放的是日志文件(.log)和索引文件(.index / .timeIndex)
2.命名:日志文件名为上一个log文件的最后一个offset的值+1,作为新的日志和索引文件名(索引和日志文件同名/仅后缀不同)。(比如00000000000000000271.log文件的上一个日志文件中最后的offset一定是270)
3.清理:日志文件和索引文件会不断被清理,依赖于topic的保留时长(log.retention.ms)和保留字节大小(log.retention.bytes)决定。
1.每个日志文件大小默认1G,可根据log.segment.bytes配置;
2.日志文件存储了消息的具体内容(offset、messageSize、data);offset类似消息自增id
索引包含两个部分(均为4个字节的数字),分别为相对offset和position
稀疏索引(像跳表)
index文件中并没有为数据文件中的每条Message建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。但缺点是没有建立索引的Message也不能一次定位到其在数据文件的位置,从而需要做一次顺序扫描,但是这次顺序扫描的范围就很小了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。