kafka回顾以及总结

kafka回顾以及总结

1、Kafka概述
    1、kafka是什么?
        kafka是基于发布/订阅的消息队列
    2、kafka应用场景?
        实时:kafka一般用于实时场景
        离线:kafka在工作中有时候会结合flume进行使用,此时kafka用于削峰
    3、基础架构
        producer: 生产者[向kafka中写入消息]
        topic: 主题,一般工作中一个业务对应一个主题
        partition: 分区
            作用:
                1、分布式存储,便于扩容
                2、提交并发,从而提高效率
        consumer group: 消费者组。工作中一个消费者组消费一个topic数据
            topic中一个分区的数只能被一个消费者组中的一个消费者所消费
            consumer group中包含多个消费者,消费者的个数最好是与topic 分区数一致
                如果consumer group中消费者个数>topic分区数,此时会有消费者没有分区数据可以消费
                如果consumer group中消费者个数<topic分区数,此时会有消费者消费多个分区的数据
        副本: 每个分区保存在不同的服务器上,如果服务器宕机,分区数据丢失,所以为了保证数据的安全性,提交了副本机制
        leader: 副本的一个角色,Producer发送数据以及消费者消费数据都找leader
        follower:副本的一个角色,主要负责同步leader的数据,如果leader宕机,会从follower中选举出新leader
        broker: kafka的一台节点,分区的存放节点
        offset: 偏移量,offset是数据在分区中的唯一标识,后续消费者组消费topic 分区数据的时候,会通过offset记录下一次应该从哪个位置开始消费
2、常用指令
    1、topic相关
        1、创建topic: bin/kafka-topics.sh --create --topic topic名称 --partitions 分区数 --replication-factor 副本数 --bootstrap-server borker主机:9092,..
        2、查看kafka集群所有的topic: bin/kafka-topics.sh --list --bootstrap-server borker主机:9092,..
        3、查看某个topic的详细信息: bin/kafka-topics.sh --describe --topic topic名称 --bootstrap-server borker主机:9092,..
        4、修改topic信息[只能修改分区数,而且是只能增加分区数,不能减少分区数]: bin/kafka-topics.sh --alter --topic topic名称 --bootstrap-server borker主机:9092,.. --partitions 分区数
        5、删除topic: bin/kafka-topics.sh --delete --topic topic名称 --bootstrap-server borker主机:9092,..
    2、消费者相关:bin/kafka-console-consumer.sh --topic topic名称 --bootstrap-server borker主机:9092,..
    3、生产者相关:bin/kafka-console-producer.sh --topic topic名称 --broker-list borker主机:9092,..
    4、数据相关: bin/kafka-dump-log.sh --files 待查看的文件路径 --print-data-log
3、原理
    1、存储结构
        Topic: 逻辑上的概念
            partition: 物理上,在磁盘中以目录的形式的存在,目录名: topic名称-分区号
                segment: 逻辑上的概念,是分区的一个段
                    index: log文件的索引
                    log: 数据存储文件
                    timeindex: log文件数据的时间索引
        segment的命名规范:
            1、每个分区第一个segment的文件名=00000000000000000
            2、第N个segment的文件名 = 第N-1个segment中最后一个offset+1
        比如此时有一个分区有三个segment: 0000000000000000、0000000000000019、0000000000000031
            0000000000000000segment中存放的是offet从0到18的数据
            0000000000000019segment中存放的是offet从19到30的数据
            0000000000000031segment中存放的是offet 31之后的数据
        如何根据offset找到数据?
            1、根据segment文件名依据二分查找法,确定offset数据在哪个segment中
            2、根据segment文件的Index索引确定数据处于log文件哪个区间
            3、根据log文件扫描区间得到offset数据
    2、生产者
        1、分区的规则<生产者的数据究竟发到哪个分区中>
            1、直接指定分区号: 数据发到指定分区中
            2、没有指定分区号,但是有key: 数据发到 (key.hashCode % 分区数) 所在分区中
            3、既没有分区号,也没有key:
                新版本:
                    1、第一个批次发送的时候,会生成一个随机数,第一个批次的数据发送 随机数% 分区数 所在分区中
                    2、第N个批次的数据发送的时候,此时会排除掉第N-1个批次发送的分区号,然后从剩余分区中随机选择一个发送
                旧版本<轮询>:
                    1、第一个批次发送的时候,会生成一个随机数,第一个批次的数据发送 随机数% 分区数 所在分区中
                    2、第N个批次的数据发送的时候,此时会发送到 (第一个批次生成的随机数+(N-1))% 分区数 所在分区中
        2、数据可靠性<生产者发送的数据是否真实的到达kafka>
            kafka通过ack机制<leader会返回确认消息给生产者,如果生产者没有收到leader的确认消息会重新发送数据>保证数据的可靠性
            ack=0: leader接受到数据之后发送返回确认消息给生产者,此时leader数据可能还没有落盘
                问题: leader返回确认消息之后宕机,因为数据还没有落盘,所有出现数据丢失
            ack=1: leader接受到数据并且落盘之后在返回确认消息给生产者
                问题: leader接受到数据并且落盘之后在返回确认消息给生产者之后宕机了,此时副本还没有同步数据,所以数据丢失
            ack=-1: leader接受到数据并且落盘,而且所有的follower都同步数据之后才会返回消息给生产者
                问题: leader接受到数据并且落盘,而且所有的follower都同步数据之后正准备返回确认消息的时候,leader宕机,此时会从follower中选举出新leader,因为原来的leader没有返回确认消息,生产者会认为数据丢失会重新发送数据给新leader,此时新leader有两份数据,数据重复
        3、数据一致性<分区副本之间数据一致>
            kafka通过isr机制保证分区副本的一致性
            后续选举leader的时候从ISR里面选举
            ISR: 与leader同步到了一定程度<副本的LEO>=集群副本的HW>的follower集合
            LEO: 每个副本最后一个offset
            HW: 所有副本中最小的LEO[表述的是已经同步完成并且返回确认消息给了生产者]
            副本故障之后重新加入ISR:
                1、leader故障: leader故障之后,首先会选举出新leader,此时其他的follower会将HW之后的所有数据清除重新从新leader同步数据,原来的leader故障解决之后,会清除宕机之前HW之后的所有数据,重新从新leader同步数据,同步到LEO>=集群HW的时候会重新加入ISR列表
                2、follower故障: follower故障之后,此时会清除HW之后的所有数据,重新从leader同步数据,同步到LEO>=集群HW的时候会重新加入ISR列表
        4、exactly once
            三种容错语义:
                exactly-once: 同一条数据发到kafka的时候有且仅有一条[数据不重复也不丢失]
                at-lest-once: 同一条数据发到kafka的时候至少一条[数据可能重复不丢失]
                at-most-once: 同一条数据发到kafka的时候最多一条[数据可能丢失]
            exactly once的原理: kafka借鉴mysql主键思想,每次发送数据的时候都会带上数据的主键[producerid+partition+sequenceNumber],broker接受到数据之后会将主键缓存,后续发送数据的时候首先会查看数据的主键在缓存中是否存在,如果存在代表该数据之前已经发送过,此时会将数据标记为无效,如果不存在则标记为有效
            exactly once的前提: ack=-1 and 开启幂等性 and 生产者不宕机
            producerid: 生产者的唯一标识[producerid是在生产者启动的时候生成的]
            partition: 分区号
            sequenceNumber: 序列化号,代表发送到分区的第几条数据
    3、消费者
        1、消费数据方式: kafka采用主动拉取数据的方式
        2、分区的分配策略:
            1、轮询: 一个分区分配给一个消费者,轮着来
                比如: 
                Topic[partition0、partition1、partition2、partition3、partition4] 
                consumer group[consumer1、consumer2]
                此时轮询的分配结果:
                    consumer1消费partition0、partition2、partition4
                    consumer2消费partition1、partition3
            2、range: 
                1、确定每个消费者平均消费几个分区: 分区数/消费者个数
                2、确定前几个消费者多消费一个分区: 分区数%消费者个数
                比如: 
                Topic[partition0、partition1、partition2、partition3、partition4] 
                consumer group[consumer1、consumer2]
                1、确定每个消费者平均消费几个分区: 分区数/消费者个数 = 5/2=2
                2、确定前几个消费者多消费一个分区: 分区数%消费者个数 = 5%2=1
                此时range的分配结果:
                    consumer1消费partition0、partition1、partition2
                    consumer2消费partition3、partition4
        3、offset的保存
            消费者组每次消费topic分区数据之后,都会记录该消费者组消费该分区的时候应该从哪个offset开始消费
            0.9版本之前offset是保存在zookeeper里面
            0.9版本之后offset是保存在kafka 内部topic<__consumer_offsets>中
    4、kafka高效读写
        1、分区: 提高并发,提高消费、写入效率
        2、顺序写磁盘: 减少磁头寻址的时间
        3、pagecache缓存
            1、生产者每个批次数据首先写入broker pagecache中,等到pagecache缓存空间不足的时候统一写入磁盘,相当于将单次写磁盘改为批次写磁盘,减少和磁盘打交道的次数
            2、pagecache中的批次数据会根据物理地址进行排序,排序之后写入磁盘可以减少磁头寻址的时间
            3、如果网络够好,生产者写入速率 = 消费者消费速率,此时数据刚刚写入page缓存中,消费者就直接从缓存中拉取数据消费了,不用经过磁盘
            4、pagecache不属于JVM管理,不会增加GC的负担
        4、零拷贝
            内存分为两块: 内核区、用户区
            从磁盘读取数据发送网络正常流程:
                1、通过io流读取磁盘数据,将数据读到内核区的pagecache中
                2、将内核区的pagecache中的数据拷贝到用户区,在用户区中对数据做处理
                3、将处理完成的数据通过io流发送到内核区的socket缓存区中
                4、将数据从socket缓存区发送到网卡
            零拷贝流程:
                1、通过io流读取磁盘数据,将数据读到内核区的pagecache中
                2、将数据从pagecache缓存区发送到网卡
    5、zookeeper在kafka作用
        kafka集群的broker节点启动的时候会选举出contoller,controller负责broker监听、leader选举等都是依赖zookeeper
        leader选举流程:
            1、启动kafka broker节点,首先会从broker中选举出一个controller
            2、broker启动之后会在zk上注册: /brokers/ids, controller会监听该路径
            3、broker中保存有很多分区,这些分区在broker启动之后也会在zk上注册: /brokers/topics/topic名称/partitions/分区号/state
            4、如果broker宕机,该broker在 /brokers/ids上的临时节点消失,controller因为在监听在路径,所以第一时间就可以得知
            5、宕机的broker中如果有leader,此时会选举出新leader, controller会更新/brokers/topics/topic名称/partitions/分区号/state中分区leader信息
    6、事务
        1、producer事务
            上述的exactly once的前提: ack=-1 and 开启幂等性 and 生产者不宕机
            如果生产者宕机,producerid以及分区号是会改变,所以生产者重启之后再发送数据,此时数据的主键已经改变,没办法保证数据有且仅有一条。
            所以kafka提供了一个事务机制。
            kafka消费者代码中会写死一个transaction.id配置,后续会将transaction.id的值与producerid绑定,将绑定结果保存在kafka内部topic中<__transaction_state>。该topic中还会保存事务的状态。
            如果生产者宕机,宕机重启之后,首先会根据transaction.id从__transaction_state中获取producerid,然后再查看事务的状态,如果事务的状态不是commit,此时会回滚事务<将上一个事务的所有数据的isValid设置为false>,此时再次开启事务进行提交
        2、消费者事务: 精准一次消费
            kafka不能保证消费者精准一次消费
4、生产者消息发送流程
    1、创建producer,将消息封装成ProducerRecord对象
    2、通过send发送消息
    3、消息首先通过拦截器进行拦截处理
    4、通过序列化器对数据进行序列化
    5、通过分区器得知数据应该发送到哪个分区
    6、将数据发送到共享变量accumulator中,等到该topic 该分区积累一个批次之后由sender线程统一发送到broker中
5、消费者拉取数据消费完成之后会提交offset,提交的offset = 消费的数据的offset+1

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值