Kafka 是一个分布式的基于发布/订阅模式的消息引擎系统
Kafka用zk管理broker
生产者:Producer。向主题发布新消息的应用程序。
消费者:Consumer。从主题订阅新消息的应用程序。消息:Record。Kafka是消息引擎嘛,这⾥里里的消息就是指Kafka处理理的主要对象。
主题:Topic。主题是承载消息的逻辑容器器,在实际使用中多用来区分具体的业务。(一个topic只有一个leader 有多个follow)
分区:Partition。一个有序不不变的消息序列列。每个主题下可以有多个分区。(一个Partition只能给一个consumer消费,一个consumer可以消费多个partition)
消息位移:Offset。表示分区中每条消息的位置信息,是一个单调递增且不不变的值。(Offset存在broker里面)
副本:Replica。Kafka中同一条消息能够被拷贝到多个地方以提供数据冗余,这些地方就是所谓的副本。副本还分为领导者副本和追随者副本,各自有不不同的⻆角⾊色划分。副本是在分区层级下的,即每个分区可配置多个副本实现高可用。
消费者位移:Consumer Offset。表征消费者消费进度,每个消费者都有自⼰己的消费者位移。
消费者组:Consumer Group。多个消费者实例例共同组成的一个组,同时消费多个分区以实现高吞吐。重平衡:Rebalance。消费者组内某个消费者实例例挂掉后,其他消费者实例例自动重新分配订阅主题分区的过程。Rebalance是Kafka消费者端实现高可用的重要手段。
生产消费
Kafka 中的消息是以主题为基本单位进⾏行行归类的,各个主题在逻辑上相互独立。每个主题又可以分为一个或多个分区,分区的数量量可以在主题创建的时候指定,也可以在之后修改。每条消息在发送的时候会根据分区规则被追加到指定的分区中,分区中的每条消息都会被分配一个唯一的序列列号,也就是通常所说的偏移量量(offset)。
不不考虑多副本的情况,一个分区对应一个日志(Log)。为了防止 Log 过大,Kafka 又引⼊入了日志分段(LogSegment)的概念,将 Log 切分为多个 LogSegment,相当于一个巨型文件被平均分配为多个相对较⼩小的文件,这样也便便于消息的维护和清理理。
向主题topic-log中发送一定量量的消息,某一时刻topic-log-0⽬目录中的布局:
Kafka 通过多副本机制实现故障自动转移,在 Kafka 集群中某个 broker 节点失效的情况下仍然保证服务可用。
我们该如何确保副本中所有的数据都是一致的呢?特别是对Kafka而⾔言,当生产者发送消息到某个主题后,消息是如何同步到对应的所有副本中的呢?针对这个问题,最常⻅见的解决方案就是采用基于领导者
(Leader-based)的副本机制。
第一,副本分成两类:领导者副本(Leader Replica)和追随者副本(Follower Replica)。
(所有的读写都在leader follow不做读写)
第二,Follower副本是不不对外提供服务的。这就是说,任何一个追随者副本都不不能响应消费者和生产者的读写请求。所有的请求都必须由领导者副本来处理理,或者说,所有的读写请求都必须发往领导者副本所在的Broker,由该Broker负责处理理。
第三,当领导者副本挂掉了,或者说领导者副本所在的Broker宕机时,Kafka依托于ZooKeeper提供的监控功能够实时感知到,并立即开启新一轮的领导者选举,从追随者副本中选一个作为新的领导者。
老Leader副本重启回来后,只能作为追随者副本加⼊入到集群中。
ISR AR
分区中的所有副本统称为 AR,而 ISR 是指与 leader 副本保持同步状态的副本集合,当然 leader 副本本身也是这个集合中的一员。
失效副本正常情况下,分区的所有副本都处于 ISR 集合中,但是难免会有异常情况发生,从而某些副本被剥离出 ISR 集合中。在 ISR 集合之外,也就是处于同步失效或功能失效(⽐比如副本处于⾮非存活状态)的副本统称为失效副本,失效副本对应的分区也就称为同步失效分区,即 under-replicated 分区。
bin/kafka-topics.sh --zookeeper localhost: 2181/kafka --describe --topic topic-partitions --under-replicated-partitions
[root@node1 kafka_2.11-2.0.0]# bin/kafka-topics.sh --zookeeper localhost:2181/ kafka --describe --topic topic-partitions --under-replicated-partitions Topic: topic-partitions Partition: 0 Leader: 1 Replicas: 1,2,0 Isr: 1,0
Topic: topic-partitions Partition: 1 Leader: 0 Replicas: 2,0,1 Isr: 0,1
Topic: topic-partitions Partition: 2 Leader: 0 Replicas: 0,1,2 Isr: 0,1
分析:
LEO与HW
LEO 标识每个分区中最后一条消息的下一个位置,分区的每个副本都有自⼰己的 LEO,ISR 中最⼩小的 LEO 即为 HW,俗称高⽔水位,消费者只能拉取到 HW 之前的消息。
(副本网络延时,会被踢出isr,避免延时过久)
分析在拉去数据过程中各个副本 LEO 和 HW 的变化情况:
仅依靠副本数来支撑可靠性是不不够的,大多数人还会想到生产者客户端参数 request.required.acks。
对于 acks = 1 的配置,生产者将消息发送到 leader 副本,leader 副本在成功写⼊入本地日志之后会告知生产者已经成功提交,如下图所示。如果此时 ISR 集合的 follower 副本还没来得及拉取到 leader 中新写⼊入的消息,leader 就宕机了,那么此次发送的消息就会丢失。
对于 ack = -1 的配置,生产者将消息发送到 leader 副本,leader 副本在成功写⼊入本地日志之后还要等待 ISR 中的 follower 副本全部同步完成才能够告知生产者已经成功提交,即使此时 leader 副本宕机,消息也不不会丢失。
对于 ack = 0 的配置这意味着producer⽆无需等待来自broker的确认而继续发送下一批消息。这种情况下数据传输效率最高,但是数据可靠性确是最低的。
#磁盘顺序读写 kafak采用的是磁盘顺序读写方式,极大提升了读写性能。
一般磁盘 I/O 的场景有以下四种:
所谓的零拷贝是指将数据直接从磁盘文件复制到网卡设备中,而不不需要经由应用程序之手。零拷贝大大提高了应用程序的性能,减少了内核和用户模式之间的上下文切换。
零拷贝
cd /usr/local/Cellar/zookeeper/3.4.10/bin
./zkServer start
./zkCli
cd /Users/vking/tools/kafka_2.11-1.0.1/bin
./kafka-server-start.sh ../config/server.properties
log /tmp/kafka-logs
./kafka-topics.sh --create --zookeeper 127.0.0.1:2181 --replication-factor 1
--partitions 1 --topic test_
./kafka-topics.sh --zookeeper 127.0.0.1:2181 --list
./kafka-console-producer.sh --broker-list 127.0.0.1:9092 --topic test_1
./kafka-configs.sh --zookeeper 127.0.0.1:2181 --entity-type brokers --entitydefault --describe
./kafka-configs.sh --zookeeper 127.0.0.1:2181 --entity-type brokers --entityname 0 --describe
./kafka-configs.sh --zookeeper 127.0.0.1:2181 --entity-type brokers --entitydefault --describe
./kafka-configs.sh --zookeeper 127.0.0.1:2181 --entity-type brokers --entityname 0 --describe