带你深入理解kafka

                                                             Kafka一款基于发布与订阅的消息系统

 

为什么要学习kafka?

认识一下kafka内部的专业术语:

Broker:一台kafka服务

Topic:消息的类别

Pratition:每一个消息的具体分区, kafka只保证在同一个分区内的消息是有序的

Reolication-factor:副本的数量不能大于 broker的数量

Offset:每个partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到partition中。partition中的每个消息

             有一个连续的序列号叫做offset,用于partition唯一标识一条消息。

replica:当某个topicreplication-factorNN大于1时,每个Partition都会有N个副本(Replica)kafkareplica包含leader与                       follower。Replica的个数小于等于Broker个数,对于每个Partition来说每个Broker上最多只会有一个Replica所有                             PartitionReplica默认情况会均匀分布到所有Broker

ConsumerGroup:多个或者1个消费者的组  消费组中的消费者不是越多越好,消费者数量超过分区数量时,会导致消费者分配不                                  到资源,造成资源浪费。

Message:消息是Kafka中最基本的数据单元,主要由key和value构成;真正有效的消息是value数据key只作为消息路由分区使                     用,kafka根据key决定将当前消息存储在哪个分区。

Producer: 负责发布消息到Kafka brokerkafka1.0以后默认异步发送,将消息放入后台队列中,然后由单独线程去从队列中取出                      消息然后发送。

Consumer:消息消费者,从Kafka broker读取消息的客户端;

Coordinator:消息消费协调通信员(负载最小 broker 节点作为该组的 Coordinator)

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

消息流转:

 1、Producer发布消息

          3种分区抉择方式:

             如果在发消息的时候指定了分区,则消息投递到指定的分区

             如果没有指定分区,但是消息的key不为空,则基于key的哈希值来mod当前topic分区数选择一个分区

             如果既没有指定分区,且消息的key也是空,则用轮询的方式选择一个分区

持久化:

    kafka消息全部持久化到磁盘,其使用日志文件的方式来保存,Partition 以文件夹的形式存储在文件系统中

   查看kafka配置可以得知日志路径 ,日志路径下可以发现有多个topic+partition名字组合而成文件,比如

   topic名为 baidu 有3个分区那么 日志路径下可以看到 baidu_0  baidu_1 baidu_2 3个文件夹 每个文件夹

   内部都有存储消息的日志文件  00000000000000000000.log

 

   

  保留消息机制

                             Kafka 的一个重要特性Kafka broker 默认的消息保留策略是这样的:要么保留一段时间(比如 7 天)

  要么保留到消息达到一定大小的字节数。当消息数量达到这些上限时,旧消息就会过期并被删除,所以在任何时刻,可用消

  息的总量都不会超过配置参数所指定的大小。主题可以配置自己的保留策略,可以将消息保留到不再使用它们为止

 

kafka会选举其中的某一个partition(备份以partition为单位)为leader,另外两个为follower。在进行数据备份时,不是leader主动将数据push给follower,而是follower去向leader pull数据过来。同时补充一个事,当kafka的consumer去消费数据的时候,并不是去follower里消费数据,依然是向leader里消费数据。follower只是起到备份数据的作用,并且follower还需要定时去leader里拿数据,如果消费数据时还向follower,这样的设置明显不合理。所以,kafka的读和写都是先通过leader的,follower只起备份作用。

分区分配选举策略:

    将所有Broker(假设共nBroker)和待分配的Partition排序

    将第iPartition分配到第(i mod n)个Broker上 (这个就是leader

    将第iPartition的第jReplica分配到第((i + j) mode n)个Broker

同步producer:  producer 发布消息后,需要成功后,才能发布下一条消息(在本文中的意思就是,producer发布数据到leader之后, 需要等所有的follower拉取到该数据后,leader才能commit。这种方式耗时)。

异步producer: producer发布消息后,无需等待即可发送下一条(即producer发送数据到leader后,leader马上commit,之后follower自己慢慢的去pull数据。这种方式可能会造成消息丢失,因为当数据到leader时,如果follower还没来得及pull数据,leader就挂了,那么这条数据就丢失了,因为leader已经向producer commit了)。

 

ISR方式:维护一个副本列表,这个列表称为ISR(in-sync-Replica)!Producer 发布消息后,它的运行机制是,当ISR  中的所有副本都pull完partition leader的数据后,即向partition leader发送ACK,此时leader再commit。并且这个ISR是动态变化的,当存在partition follower同步数据大步落后于partition leader时,则会将其从ISR中移除,以免拖垮整个进度,并且当不在ISR中的partition follower,与partition leader同步时, partition leader又会将其加入到ISR中。这样的机制,不像同步和异步那么绝对,即保证了速度也保证了数据的安全性。当然如果follower如果挂了,则也会将其从ISR中移除(leader也会存在于ISR列表中)

      commit:只要leader commit了,即向producer表示这条数据已经被存储在broker了,对于producer来说就是这条数据已经被成功发布

 

    Producer幂等性:解决:生产者重复生产消息,因为生产者进行retry重试时,会重复产生消息

    

        幂等性实现

        PID每个新的Producer在初始化的时候会被分配一个唯一的PID,这个PID对用户是不可见

        Sequence Numbler对于每个PID,该Producer发送数据的每个<Topic, Partition>都对应一

                                          从0开始单调递增的Sequence Number

 

        Broker端在缓存中保存了这seq number,对于接收的每条消息,如果其序号比Broker缓存中序号

        于1则接受它,否则将其丢弃。这样就可以实现了消息重复提交了。能保证单个Producer

        于一个Topic 同一个Partition的幂等。

              

        enable.idempotence

           当设置为‘true’,生产者将确保每个消息正好一次复制写入到stream。如果‘false’,由于broker故障,

           生产者重试。即,可以在流中写入重试的消息。此设置默认是‘false’。请注意,启用幂等式需要将

           max.in.flight.requests.per.connection设置为1,重试次数不能为零。另外acks必须设置为“全部”。

           如果这些值设置为与幂等生成器不兼容的值,则将抛出一个ConfigException异常。

2.Consumer消息消费:

同一时刻,一条消息只能被group中的一个消费者实例消费,一个topic下的每个partition只从属于group中的一个消费者,不可能出现group中的两个消费者消费同一个分区。为了提高消费端的消费能力,一般会通过多个consumer 去消费同一个 topic ,如果 分区为123,消费者也为123,那么会给每个消费者分配且仅分配一个分区来消费。如果消费者还有个4,那么4会空闲,因为每个分区都有了一个消费者。如果消费者为12,那么其中有一个消费者消费两个分区,另一个消费一个分区。所以消费者的数量不要大于分区,否则会造成资源浪费。消费者的数量最好控制为分区的数量,这样能为消费者合理分配分区

 

 

Kafka消息在分区内有序,消费者消费消息时也要按照分区内消息顺序进行消费,有序消费就要保证消息是由消费者主动拉取的(pull),其次还要保证一个分区只能由一个消费者负责。kafka消费者自己可以控制读取消息的offset,如果两个消费者负责同

一个分区,就有可能C1读到2C1还没处理完,C2已经读到3了,因为这就相当于多线程读取同一个消息,造成重复消费,而且

能保证消息的顺序

 

  Rebalance 机制:解决一个 consumer group 下的所有 consumer 合理分配订阅 topic的每个分区 

      

   rebalance 过程:

                    join:    在这一步中,所有的成员都会向 coordinator 发送 joinGroup 的请求。一旦所有成员都发送了 joinGroup 请求

                              那么 coordinator 会选择一个 consumer 担任 leader 角色,并把组成员信息和订阅信息发送消费者

                   syncleader制定分区消费分配方案发送给coordinatorcoordinator将分配方案发送到组中所有消费者。这样所有成员

                              都知道自己应该消费哪个分区。

             generation_id:每一轮 rebalance 都会导致 generation_id 递增,防止脑裂问题。

              

 

       消费者分区分配策略

         假设我们创建了一个主题,并且8个分区p0-p8,我们有3个消费者c0-c2

    range策略(分区按照顺序平铺,消费者按照顺序平铺

       假设区分数量为pCout,消费者数量为cCount

       n = pCout / cCount   8  / 3 = 2

       m = pCount % cCount  8 % 3 = 2

       前m消费者得到n+1分区,剩余的消费

       者分配n分区

     roudRobin(轮询

         8个分区按照顺序平铺

         构造消费者环 c0,c1,c2,c0,c1,c2.......

         轮询分配过程是  p0 分配给了 c0, p1 分配给了 c1, p2分配给了 c2, p3分配给了c0, p4分配给了 c1, p5分配给了c2, 一次类推,           所有分区轮询分配给一个消费者环

           

      coordinator执行 Rebalance 以及管理 groupgroup 中的 consumer 启动的时候,它会去和 kafka server

      确定谁是它们组的 coordinator。consumer group 内所有consumer都会和该 coordinator 进行协调通信

 

新增分区,组内消费者增加,组内消费者减少 都会出发coordinator执行rebalance

 

 

Kafka 老版本是通过zookeeper 记录消费的位置 

新版本kafka 交给broker服务来管理

管理方式:

第一次消费会自动创建一个名为__consumer_offsets的topic, 默认有50个分区,每一个有Consumer group消费的时候都会将消费的位置记录到__consumer_offsets,至于记录到那个分区是通过 求group的hash 值 %__consumer_offsets的partition数量来决定存在那个parttion

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

broker和集群

borker:

 broker 接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。broker 为消费者提供服务,

对读取分区的请求作出响应,返回已经提交到磁盘上的消息。根据特定的硬件及其性能特征,单个 broker

可以轻松处理数千个分区以及每秒百万级的消息量。

集群:

broker 集群的组成部分。每个集群都有一个 broker 同时充当leader的角色!leader负责管理工作,包括将

区分配给 broker 和监控 broker。在集群中,一个分区从属于一个 broker,该 broker 被称为分区的首领。一个分

区可以分配给多个 broker,这个时候会发生分区复制。这种复制机制为分区提供了消息冗余,如果有一个 broker

失效,其他 broker 可以接管领导权。不过,相关的消费者和生产者都要重新连接到新的首领

 

 

Kafka集群中,每个Broker在启动时会实例化一个KafkaController类。该类会执行一系    列业务逻辑,选举出主题分区的Leader节点,不是leader的节点

 kafka Broker Leader的选举

       Kakfa Broker集群受Zookeeper管理。集群启动后所有的Kafka Broker节点一起去Zookeeper上注册一个临时节点,因为只有一 

      个Kafka Broker会注册成功,其他的都会失败,所以这个成功在Zookeeper上注册临时节点的这个KafkaController我们就叫他

       Kafka Broker leader其他的Kafka broker我们叫它Kafka Broker follower。Kafka Broker leader会维护一个基本与其保持同步

      的副本列表也就是上面的ISR

       其他的Kafka Broker follower会ZooKeeper注册Watch 。这个leader监听其他的Kafka Broker的所有信息。

 kafka broker leader宕机:(包括但不限于机器断电,网络不可用,GC导致的Stop The World,进程crash等),

       在zookeeper上的那个临时节点就会自动消失此时zookeeper会通知所有kafka broker,这个时候所有的存活的broker会           一起去Zookeeper 上注册一个临时节点进行抢leader位置。

 

Broker宕机:

        这个kafka broker leader读取该宕机broker上所有的partitionzookeeper上的状态,并选取ISR列表中的一个replica作为                partition leader(如果ISR列表中的replica全挂,选一个幸存的replica作为leader; 如果该partition的所有的replica都宕机了,            则将新的leader设置为-1,等待恢复,等待ISR中的任一个Replica“活”过来,并且选它作为Leader;或选择第一个“活”过来的            Replica(不一定是ISR中的)作为Leader),这个broker宕机的事情,kafka leader会通知zookeeperzookeeper就会通

        知其他的 kafka broker

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

kafkajava垃圾回收的选择:

常用命令:

 

常用命令:

kafka-server-start.sh -daemon  启动

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test 创建topic

bin/kafka-topics.sh --list --zookeeper localhost:2181 展示topic列表

kafka-console-producer.sh --broker-list 130.51.23.95:9092 --topic my-replicated-topic  启动一个生产者

kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginnin

 

 

kafka-consumer-groups.sh  --group console-consumer-60979 --describe --bootstrap-server localhost:9092   查看消费组消费详情

kafka-consumer-groups.sh  --bootstrap-server localhost:9092 --to-offset 1 --reset-offsets  --group console-consumer-60979   --topic xxxxx  --execute重置offset

kafka-consumer-groups.sh  --all-groups --bootstrap-server localhost:9092  查看消费者组列表

 kafka-consumer-groups.sh   --bootstrap-server localhost:9092 --members --describe  --group console-consumer-23544 查看具体某个消费者

kafka-run-class.sh kafka.tools.DumpLogSegments --files 00000000000000000000.log --print-data-log 消息日志查看

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值