Kafka 初探

KAFKA学习笔记

  • 什么是消息队列?

    • A系统发消息给B系统,不会直接发送过去,而是直接发给消息队列,消息队列进行缓存。
    • 消息队列分为一对多推送订阅模式。也分为一对一,消费者主动拿去数据模式。
  • 为什么需要消息队列,优点是什么?

    • 解耦
    • 灵活性,和峰值处理能力。可以应对大量的并发请求
    • AB系统故障了,不会导致队列的消息丢失
    • 缓冲
    • 异步通讯,就是我A消息发出去,不想B马上处理,也就是放入队列中,消费者想什么时候消费就什么时候消费。
  • kafka基本架构就是

    生产者、kafka集群,消费者。
    进一步看他的结构:
    kafka实例 broker,

  • topic是存数据的,可以认为是数据库中的一张表

  • 同一个topic的消息可分布在多个节点broker上

  • 一个topic包含一个或者多个partition

  • 每条消息都属于且仅属于一个topic

  • 下图我们可以看到几个点:

    • 同一个topic可以在多个broker中,这个是对的,集群嘛,就是这样
    • 但是多个broker中相同的topic的partition是不会一样的
    • 多个broker相同topic的partition是均匀分布的

Kafka 初探_第1张图片

  • Partition

    • 一个partition只分布在一个broker中
    • 一个partition物理是一个文件夹,理解为一个队列:实际的我们去看kafka的日志文件,就会发现有多少个partition就有多少个文件夹,名字是topic1-0…。
    • 一个partition包含多个segment
    • 一个segment对应一个文件,这个文件的名字就是offset
    • segment是从后追加记录(AOF也是)

    kafka的过期时间默认168小时,如果超过,就会删除segment文件。策略也有是按大小来删除。

  • 建立kafka集群:

    • bin目录下 启动zookeeper

    • 启动kafka-server-start 配置文件

      配置文件中可以指定端口,bokerid,日志目录(其实就是partition),partition数量

    • // 创建topic,并且他的partition数量是3个
      sh kafka-topics.sh --zookeeper localhost:2181 --create --topic test1 --partitions 3 --replication-factor 1 
      
      //  这条命令让我们看到创建的topic
      sh kafka-topics.sh --zookeeper localhost:2181 --describe --topic test1
      
    • // 创建一个消费者
      sh kafka-console-consumer.sh --zookeeper localhost:2181 --topic test1
      
    • // 创建一个生产者,给指定broker和topic放入数据
      sh kafka-console-producer.sh --broker-list localhost:9092 --topic test1
      
  • 消息怎么知道去哪个partition呢?

    有几个策略:在接口partitioner中实现

    • 哈希一致算法,根据key的hash值来确定
    • 循环,一个一个来。RoundRobin
  • 同步的生产者和异步的生产者

    • 同步:我把消息放到partition中,必须消费完,才能放入下一个,如果失败就是重试,超过三次就会抛出,好处就是低延迟但是吞吐量不高(当然我们可以一次性发送一组数据)。
    • 异步反之。是有个队列,放在队列中。只有等到队列达到一定长度或者一定时间的时候,才会发送。
  • replica

    1. 个partition会有N个replica,这些replica会均匀分布在不同的broker中。绝对不再自己leader那个broker中
      Kafka 初探_第2张图片

    2. replica要解决的问题:

      • 怎么如何将数据扩散出去

        producer讲数据给到leader,follower是主动去拉取的,这和消费者主动去拉是相似的。

        读操作也是读leader的数据

      • 何时commit

        commit是指什么时候告诉producer你的数据我已经保存了,这个时候kafka一定要保证这条数据是不能丢失的。我们首先讲一下同步复制和异步复制,同步复制就是等到follow全部复制leader的数据完成,才发送commit,异步就是leader得到了数据以后就发送commit。

        kafka的策略呢?既有同步也有异步,他的leader维护了一个他所有follwer的列表ISR,如果这些follwer中有的落后太多(可以设置参数,可以是相差的时间,可以是相差的数据),就把这些follwer移除,另外如果这些follwer慢慢的恢复过来,就把他们重新加进来。当所有的follwer都给leader发送ack的时候,leader就commit。

      • 如何处理replica恢复Kafka 初探_第3张图片
        (1). 第一点说的是指提交m1

        (2). 第二点说的是leaderA挂了,B做Leader,同步到m2

        (3). 再来个数据m5

        (4). A回来了,会去先同步之前的信息。

      • 如何处理replica全部宕机

        默认是第一个恢复的replica作为leader

  • 深入学习kafka的高可用设计:、

    • 选举算法:ISR
      ISR列表存在zookeeper上
      选举leader的基本原则是:如果leader不在了,新的leader必须拥有原来的leader的所有commit过的消息。在这些follwer中选一个。
    • 如何确认follwer是否跟上了leader呢?
      replica.lag.max.message 落后的消息个数
      relica.lag.time.max.ms 多长时间没有去fetch leader的数据
    • commit的选择,要么异步要么同步,但是他折中了。
    • ISR中至少需要一个replica
  • 面试问题:

    • Kafka 选主怎么做的?
      要说多一点,kafka在zookeeper中维护了一个ISR队列,包含leader和follwer,follwer会间隔时间的主动拉取leader的数据,如果一致的话,那么这份数据就是commit状态,而我们选择主应该是去ISR列表中寻找和宕机的leader commit数据一样的follwer。
    • zookeeper选举是怎么实现的呢?
      投票数大于半数则胜出的机制。
      一些概念:
      myid是一个服务器的id,id越大在投票中的算法中权重越大,是在配置集群的时候配置的。
      数据id:是服务器中存放最新数据版本号,数字越大说明数据越新,选举过程中权重也就越大。
      逻辑时钟:就是这台机器参与投票的次数。
      选举机制有分为第一次全新选举,非全新选举
      • 全新选举,每个节点给自己投票,然后广播自己的投票信息给其他服务器,进行交换比较,在其他服务器中确定胜出的结果,然后投票给胜出的服务器。如果胜出的数量超过一半,那么就是他获胜了,后面进来的服务器不会再参与选举。
      • 非全新选举:如果原来的leader宕机了。首先比较逻辑时钟,时钟小的说明过程中有发生过宕机,所以不选它。之后对比数据的新旧。在之后比较编号。也就是选择原则是最可靠的,数据最完整的服务器。
    • 为什么要用ISR原理呢?
      选主的算法很多,比如zk的zab算法,raft的Viewstamped Replication 算法。区别是什么呢?区别很大,但是实现上,就是其他算法的每个replica都需要一个watch来监控选举过程。而kafka是先选出一个controller来执行isr列表的判断。
    • rabbitMQ和kafka的区别:
      看了篇文章加上我们上面的结构图,看起来本质的原因是。rabbitMQ缺点是吞吐量不够大。kafka有一个tipic的概念,一个topic可以分布在多个broker机器上(但是partition不同),这样当有很高的请求时,多个机器来一起扛住压力。而rabbitMQ没有topic,他的队列就是在一个broker上,需要一个服务器去承担压力,这也是kafka 为什么可以扛住这么高的qps的原因。
    • kafka怎么保证数据不会丢失:
      配置ack参数,或者是ack机制。当ack=0,producer把消息发出去了,partition就算没有数据落到磁盘上也认为数据到了kafka,可以被消费,但是如果此时宕机了,那就完蛋了。当ack=1,就是当partion记录到了这个记录并落到了磁盘上,但是还没有被follwer同步,如果这个时候宕机了,再次选举leader的时候就会缺少这个数据。而kafka默认的是这个模式。当ack=all的时候,必须等到follwer全部同步了才可以。
  • kafka中的zookeeper是干嘛的
    zookeeper中存放了关于consumer和broker的信息

    • broker
      zookeeper记录了所有broker的状态,broker会有一个心跳线程去上报自己的状态。
      zookeeper负责kafka的控制器选举,kafka集群中有一个控制器,管理所有分区和副本,当leader挂了,他负责去选举新的leader,我们知道是ISR动态列表。
      因此其实zookeeper中保存了一个ISR列表
      topic的访问权限,topic的相关信息,比如在那个broker中,有几个parition
    • consumer
      在zookeeper中注册
      kafka 的每个 partition 只能被消费组中的一个 consumer 消费,kafka 必须知道所有 partition 与 consumer 的关系。 当然了这个parttion可以分配各其他消费组的consumer消费。
  • 怎么保证kafka的消费有序性
    kafka只能保证partition内是有序的,但是partition间的有序是没办法的。 除非你只用一个partion,或者人为的把消息都放在一个partition中,这样肯定是有序的,但是这样就舍弃了分布式的优势,似乎你就不应该选择kafka。

  • 杂记:
    kafka设计消费者主动去poll队列中的消息。那么消费者怎么确定去哪个broker里那数据呢?通过zookeeper,zookeeper里面有全部broker集群的信息,包括partition,topic有多少个,在哪里。
    producer怎么发现集群呢,先去一个broker,如果失败就去重连,访问缓存,获取全部broker,topic信息。
    producer发送的所有信息,都要指定要发送到那个topic中。consumer在订阅的时候也要指定要订阅哪个topic消息。
    消费者消费以后要到zookeeper中记录offset,发布到哪里了
    消费者,只能消费leader
    kafka是只能消费者消费队列数据的,没有推送的模式
    6)Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)。kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition间)的顺序;
    7)Offset:kafka的存储文件都是按照offset.kafka来命名,用offset做名字的好处是方便查找。例如你想找位于2049的位置,只要找到2048.kafka的文件即可。当然the first offset就是00000000000.kafka。

    • 消费者是以consumer group消费者组的方式工作,由一个或者多个消费者组成一个组,共同消费一个topic。
    • consumer采用pull(拉)模式从broker中读取数据。
      push(推)模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而pull模式则可以根据consumer的消费能力以适当的速率消费消息。
      对于Kafka而言,pull模式更合适,它可简化broker的设计,consumer可自主控制消费消息的速率,同时consumer可以自己控制消费方式——即可批量消费也可逐条消费,同时还能选择不同的提交方式从而实现不同的传输语义。
      pull模式不足之处是,如果kafka没有数据,消费者可能会陷入循环中,一直等待数据到达。为了避免这种情况,我们在我们的拉请求中有参数,允许消费者请求在等待数据到达的“长轮询”中进行阻塞(并且可选地等待到给定的字节数,以确保大的传输大小)。

你可能感兴趣的:(linux,kafka)