文章来源于本人的印象笔记,如出现格式问题可访问该链接查看原文

原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94

副本机制

Kafka的副本机制会在多个服务端节点上对每个主题分区的日志进行复制,当集群中的某个节点上出现故障时,访问故障节点的请求会被转移到其他正常节点的副本上,副本的单位是主题的分区;

kafka每个主题的每个分区都会有一个主副本(Leader)以及0个或多个备份副本(Follower),主副本负责客户端的读和写,备份副本则负责向主副本拉取数据,以便和主副本的数据同步,当主副本挂掉后,kafka会在备份副本中选择一个作为主副本,继续为客户端提供读写服务;

分区的主副本应该均匀的分布在各个服务器上,如上图所示,通常主题分区的数量要比服务器的数量多很多,所以每个服务器都可以成为一些分区的主副本,也能同时成为一些分区的备份副本;

备份副本始终尽量保持与主副本的数据同步,备份副本的日志文件和主副本的日志总是相同的,它们都有相同的偏移量和相同顺序的消息。

容错处理

分布式系统处理故障容错时,需要明确的定义节点是否处于存活状态,kafka对节点的存活定义有如下两个条件

  1. 节点必须和ZK保持会话
  2. 如果这个节点是某个分区的备份副本,他必须对分区主副本的写操作进行复制,并且复制的进度不能落后太多

满足上述两个条件,叫做(in - sync)正在同步中,每个分区的主副本会跟踪正在同步中的备份副本节点(In Sync Replicas 即ISR ),如果一个备份副本挂掉,没有响应或者同步进度落户太多,主副本就会将其从同步副本集合中移除,反之,如果备份副本重新赶上主副本,它就会加入到主副本的同步集合中;(这个主副本的同步集合,包含主副本自己以及主副本保持一定同步的备份副本 则统称为ISR)

在Kafka 中,一条消息只有被ISR集合的所有副本都运用到本地的日志文件,才会认为消息被成功

提交了, 任何时刻,只要ISR至少有一个副本是存活的, Kafka就可以保证“一条消息一旦被提交,就不会丢失” 只有已经提交的消息才能被消费者消费,因此消费者不用担心会看到因为主副本失败而

丢失的消息;

对于生产者所发送的一条消息已经写入到主副本中,但是此时备份副本还没来及进行数据copy时,主副本就挂掉的情况,那么此时消息就不算写入成功,生产者会重新发送该消息,当所发送的一条消息成功的复制到ISR的所有副本后,它们才会被认为是提交的,此时才对消费者是可见的。

服务验证

验证kafka的服务副本机制和容错处理。

验证kafka的副本机制,只需部署一台测试用kafka即可,验证kafka的容错处理,及服务节点down机后的处理方式,则需要最低3个服务搭建kafka集群进行模拟;

单节点验证

先官网下载一个kafka,也可以在此处网盘直接下载

链接:https://pan.baidu.com/s/1_tmQA1AqTgh4T81HuW8OlA
提取码:zc1q

修改config目录下server.properties内容的基本信息,此处修改内容如下

broker.id=1
listeners=PLAINTEXT://10.0.3.17:9092
log.dirs=/opt/gangtise/kafka/kafka_2.11-2.1.0/logs/kakfa_tmp
zookeeper.connect=10.0.3.17:2181

zookeeper.properties内容保持不变,然后启动kafka默认自带的zk服务,以及kafka服务即可;

启动zk
./zookeeper-server-start.sh -daemon /opt/gangtise/kafka/kafka_2.11-2.1.0/config/zookeeper.properties 启动kafka
./kafka-server-start.sh -daemon /opt/gangtise/kafka/kafka_2.11-2.1.0/config/server.properties

新建一个只有一个副本一个分区的topic主题

[root@dev bin]# ./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic arnold_test

WARNING: Due to limitations in metric names, topics with a period ('.') or underscore ('_') could collide. To avoid issues it is best to use either, but not both.
Created topic "arnold_test".

此时在我们所配置的tmp文件夹下则对应新建了一个相同topic名称的日志文件,由于我们此时新建

arnold_test topic时只指定创建了一个分区,所以该日志目录下只创建了一个分区文件夹;索引位为0;

除此之外,还可以看到在我们所产生的分区文件同级别的目录下,存在如下4个 checkpoint结尾的文件,其中 replication-offset-checkpoint(复制偏移检查点) 记录对应的各主题分区的偏移量;recovery-point-offset-checkpoint(恢复点偏移检查点) 记录对应的各主题分区的恢复点的偏移量;做个标记,后续给详细的说明

[root@dev kakfa_tmp]# pwd
/opt/gangtise/kafka/kafka_2.11-2.1.0/logs/kakfa_tmp
[root@dev kakfa_tmp]# ll
total 16
drwxr-xr-x. 2 root root 141 Nov 25 17:21 arnold_test-0
-rw-r--r--. 1 root root 0 Nov 25 17:12 cleaner-offset-checkpoint
-rw-r--r--. 1 root root 4 Nov 25 17:24 log-start-offset-checkpoint
-rw-r--r--. 1 root root 54 Nov 25 17:12 meta.properties
-rw-r--r--. 1 root root 20 Nov 25 17:24 recovery-point-offset-checkpoint
-rw-r--r--. 1 root root 20 Nov 25 17:24 replication-offset-checkpoint

查看arnold_test-0这个分区下的内容如下,其中 .log 结尾的文件则是二进制的日志文件,该日志文件中所存储的内容则是我们通过kafka生产者向这个topic中所输入的消息内容;可以使用 string 命令查看该二进制文件的内容。

[root@dev arnold_test-0]# pwd
/opt/gangtise/kafka/kafka_2.11-2.1.0/logs/kakfa_tmp/arnold_test-0
[root@dev arnold_test-0]# ll
total 4
-rw-r--r--. 1 root root 10485760 Nov 25 17:21 00000000000000000000.index
-rw-r--r--. 1 root root 0 Nov 25 17:21 00000000000000000000.log
-rw-r--r--. 1 root root 10485756 Nov 25 17:21 00000000000000000000.timeindex
-rw-r--r--. 1 root root 8 Nov 25 17:21 leader-epoch-checkpoint

再新建一个只有一个副本三个分区的topic主题

./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 3 --topic arnold_test_many

查看日志分区文件如下

[root@dev kakfa_tmp]# pwd
/opt/gangtise/kafka/kafka_2.11-2.1.0/logs/kakfa_tmp
[root@dev kakfa_tmp]# ll
total 16
drwxr-xr-x. 2 root root 141 Nov 25 17:21 arnold_test-0
drwxr-xr-x. 2 root root 141 Nov 25 19:18 arnold_test_many-0
drwxr-xr-x. 2 root root 141 Nov 25 19:18 arnold_test_many-1
drwxr-xr-x. 2 root root 141 Nov 25 19:18 arnold_test_many-2
-rw-r--r--. 1 root root 0 Nov 25 17:12 cleaner-offset-checkpoint
-rw-r--r--. 1 root root 4 Nov 25 19:19 log-start-offset-checkpoint
-rw-r--r--. 1 root root 54 Nov 25 17:12 meta.properties
-rw-r--r--. 1 root root 83 Nov 25 19:19 recovery-point-offset-checkpoint
-rw-r--r--. 1 root root 83 Nov 25 19:20 replication-offset-checkpoint

使用console 生产者,向arnold_test_many topic生产6条数据,可以看到此时我们生成6条content内容,按照我们上一章的说法,由于我们没有使用key值的方式进行存储,而是直接存储的内容,那么此时所产生的6条内容,则会按照轮训的方式依次插入对应的分区中。

[root@dev bin]# ./kafka-console-producer.sh --broker-list 10.0.3.17:9092 --topic  arnold_test_many
>message1
>message2
>message3
>message4
>message5
>message6

此时我们直接查看kafka分区偏移量记录的文件,可以看到arnold_test_many 0,arnold_test_many 1,arnold_test_many 2 所对应的分区 所对应的偏移量都是2,因为我们此时插入了6条数据,轮训均衡的插入到了3个分区中,所以各个分区中的检查点偏移量都为2。

[root@dev kakfa_tmp]# pwd
/opt/gangtise/kafka/kafka_2.11-2.1.0/logs/kakfa_tmp
[root@dev kakfa_tmp]# cat replication-offset-checkpoint
0
4
arnold_test_many 2 2
arnold_test_many 1 2
arnold_test 0 0
arnold_test_many 0 2

此时我们使用strings 直接查看各分区中所存储的日志内容

[root@dev arnold_test_many-0]# pwd
/opt/gangtise/kafka/kafka_2.11-2.1.0/logs/kakfa_tmp/arnold_test_many-0
[root@dev arnold_test_many-0]# strings 00000000000000000000.log
message2
message5
[root@dev arnold_test_many-1]# pwd
/opt/gangtise/kafka/kafka_2.11-2.1.0/logs/kakfa_tmp/arnold_test_many-1
[root@dev arnold_test_many-1]# strings 00000000000000000000.log
message1
message4
[root@dev arnold_test_many-2]# pwd
/opt/gangtise/kafka/kafka_2.11-2.1.0/logs/kakfa_tmp/arnold_test_many-2
[root@dev arnold_test_many-2]# strings 00000000000000000000.log
message3
message6

如上所示,数据采用轮训的方式均匀的插入到了各个分区中,整理后结果如下所示。

arnold_test_many1    arnold_test_many0    arnold_test_many2
message1 message2 message3
message4 message5 message6

此时可能你会有如此疑问,为什么数据的轮训不是从 arnold_test_many0开始轮训插入的,而是从arnold_test_many1开始的?这个我还没做严格测试,所以不排除轮训的起始分区的确是随机的,至少并不是按照分区的下标来确定顺序的。不过该topic的分区的顺序只要第一次插入数据确定后,后续就都将按照这个顺序执行,所以,起始分区的确也不是最重要的问题了。

此时我们使用消费者来消费该topic下的所有分区内的数据,可以看到消费者消费kafka中的数据时,并没有按照生产者的插入顺序来读取出来;这也验证了我们上一章的说法,kafka并不保证当前topic的全局消息顺序,而只是保证当前该topic下各分区的消息顺序,也就是我们看到的 分区arnold_test_many2中的message3消息一定在message6前面,分区 arnold_test_many1中的 message1肯定在message4前面;

[root@dev bin]# ./kafka-console-consumer.sh --bootstrap-server  10.0.3.17:9092  --from-beginning --topic arnold_test_many
message3
message6
message1
message4
message2
message5

原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94

分布式模式验证

直接将我们kafka的部署包,分别cp到不同的机器上,然后修改对应的配置,启动即可,主要配置内容如下

10.0.3.17

broker.id=1
listeners=PLAINTEXT://10.0.3.17:9092
log.dirs=/opt/gangtise/kafka/kafka_2.11-2.1.0/logs/kakfa_tmp
zookeeper.connect=10.0.3.17:2181

10.0.6.39

broker.id=2
listeners=PLAINTEXT://10.0.3.17:9092
log.dirs=/home/gangtise/kafka/kafka_2.11-2.1.0/logs/kafka_tmp
zookeeper.connect=10.0.3.17:2181

10.0.3.18

broker.id=3
listeners=PLAINTEXT://10.0.3.18:9092
log.dirs=/opt/gangtise/kafka/kafka_2.11-2.1.0/logs/kafka_tmp
zookeeper.connect=10.0.3.17:2181

启动对应的kafka节点后,通过zk的图形化工具查看当前的kafka注册信息,可以看到对应的kafka节点信息都已经注册到zk上,此时表明部署完成;(由于此处主要是验证下kafka集群的特性,所以zk的节点则只部署了一个,测试用即可)

新建Topic

由于我们此时已经有了3个服务器节点,对应的服务器broker.id分别为:1,2,3;

此时我们创建一个新的Topic,指定该Topic为三个副本,三个分区,如下:--replication-factor 3 表示创建对应的副本数为3, --partitions 3 表示创建对应的分区数为3

./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 3 --partitions 3 --topic arnold_test_many_three

使用--describe命令查看该topic的详细信息

[root@dev bin]# ./kafka-topics.sh --describe  --zookeeper 10.0.3.17:2181 --topic arnold_test_many_three

Topic:arnold_test_many_three    PartitionCount:3        ReplicationFactor:3     Configs:
Topic: arnold_test_many_three Partition: 0 Leader: 3 Replicas: 3,1,2 Isr: 3,1,2
Topic: arnold_test_many_three Partition: 1 Leader: 1 Replicas: 1,2,3 Isr: 1,2,3
Topic: arnold_test_many_three Partition: 2 Leader: 2 Replicas: 2,3,1 Isr: 2,3,1

上述查询结果详细解释一下,如下:

第一行含义是:

Topic arnold_test_many_three 一共有三个分区(PartitionCount:3),三个副本(ReplicationFactor:3),对应的配置的具体信息,则是看下方的详情(Config)

第二行含义是:

Topic arnold_test_many_three 的第0个分区(Partition: 0),对应的主副本Leader节点是3(Leader: 3),该0分区对应的副本分别是在3,1,2节点上存储(Replicas: 3,1,2),其中当前的ISR信息分别是3,1,2(Isr: 3,1,2);

那么对应的第三行的含义则也是与第二行相似,表示当前的 Partition 1分区的三个副本,分别是在broker.id 为1,2,3的三个服务节点上存储,其中主副本Leader副本则是broker.id为1的服务器上的副本,则是主副本;当前该分区的同步信息 isr 是1,2,3,表示所有节点均同步正常;

ISR表示正在同步的节点集合,详细解释,可以看上述容错处理中的内容解释;

手动停止节点

此时我们将broker.id为2的节点服务停止掉,再观察下当前的副本情况;

直接使用kill -9 强制进程退出的方式;
[gangtise@yinhua-ca000003 arnold_test_many_three-0]$ kill -9 94130

此时再观察对应的topic的详细信息

[root@dev bin]# ./kafka-topics.sh --describe  --zookeeper 10.0.3.17:2181 --topic arnold_test_many_three
Topic:arnold_test_many_three PartitionCount:3 ReplicationFactor:3 Configs:
Topic: arnold_test_many_three Partition: 0 Leader: 3 Replicas: 3,1,2 Isr: 3,1
Topic: arnold_test_many_three Partition: 1 Leader: 1 Replicas: 1,2,3 Isr: 1,3
Topic: arnold_test_many_three Partition: 2 Leader: 3 Replicas: 2,3,1 Isr: 3,1

可以看到,分区的主副本已经进行了转移,原先的Partition 2 分区的,Leader节点由原来的2,变更为了现在的3;

也就是说当前的Partition2分区的Leader节点主副本任务由原来的2服务器节点,变更成了由服务器节点3来接管Partition2分区的主副本任务;

另外则是,所有的Replicas 副节点的信息,是没有变化的,还是和以前的一摸一样,毕竟2节点只是down机,修复好以后还是要重新承担副本的任务的;

虽然每个分区的Replicas没有变化,但是每个分区的ISR中不再包含 2节点;(也就是说,后续的消息的同步集合中,只需要1,3节点同步完成,则同步完成,便会直接给生产者返回一个消息,OK同步完成;而2节点,等到后续节点修复后,主动copy其他分区的副本内容到自身的节点上,等到进度完全和其它节点保持一致后,则重新加入到ISR同步集合中。)

那么此时,我们再重新启动下 2节点;

[gangtise@yinhua-ca000003 kafka_2.11-2.1.0]$ ./bin/kafka-server-start.sh -daemon /home/gangtise/kafka/kafka_2.11-2.1.0/config/server.properties

然后再重新查看当前Topic的详细信息,啪一下啊,很快啊,可以看到ISR中的同步集合中,2节点也已经正常回归;

[root@dev bin]# ./kafka-topics.sh --describe  --zookeeper 10.0.3.17:2181 --topic arnold_test_many_three

Topic:arnold_test_many_three    PartitionCount:3        ReplicationFactor:3     Configs:
Topic: arnold_test_many_three Partition: 0 Leader: 3 Replicas: 3,1,2 Isr: 3,1,2
Topic: arnold_test_many_three Partition: 1 Leader: 1 Replicas: 1,2,3 Isr: 1,3,2
Topic: arnold_test_many_three Partition: 2 Leader: 3 Replicas: 2,3,1 Isr: 3,1,2

如上,可以看到,此时的ISR中已经包含了2节点;但是,观察上面结果可以看到,Partition0分区和Partition2分区的主节点都还是在 3服务器节点上,也就是当前该两个分区都过于依赖3服务器的主副本节点,而主副本节点又要负责消息的读写的任务,所以3服务节点,压力较大,此时通过执行平衡操作,来解决分区主节点的问题

执行自平衡

[root@dev bin]# ./kafka-preferred-replica-election.sh --zookeeper 10.0.3.17:2181

[root@dev bin]# ./kafka-topics.sh --describe  --zookeeper localhost:2181 --topic arnold_test_many_three
Topic:arnold_test_many_three PartitionCount:3 ReplicationFactor:3 Configs:
Topic: arnold_test_many_three Partition: 0 Leader: 3 Replicas: 3,1,2 Isr: 3,1,2
Topic: arnold_test_many_three Partition: 1 Leader: 1 Replicas: 1,2,3 Isr: 1,3,2
Topic: arnold_test_many_three Partition: 2 Leader: 2 Replicas: 2,3,1 Isr: 3,1,2

Partition2的副本集[2,3,1],原有的Leader编号是3,通过执行上述平衡操作后,分区2的主副本节点由原有3,迁移到了节点2。

不过,如果在服务down机后,不手动执行平衡操作的情况下,那么过一段时间,kafka会自动进行一下平衡,只要新上来的服务是稳定的情况下,kafka会自动将主副本平衡到新的节点上;

命令汇总

上述所使用到的几个命令汇总

创建Topic
./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 3 --topic arnold_test_many 生产者
./kafka-console-producer.sh --broker-list 10.0.3.17:9092 --topic arnold_test_many 消费者
./kafka-console-consumer.sh --bootstrap-server 10.0.3.17:9092 --from-beginning --topic arnold_test_many 查看Topic详细信息(包含节点的分布情况)
./kafka-topics.sh --describe --zookeeper 10.0.3.17:2181 --topic arnold_test_many_three 分区自平衡
./kafka-preferred-replica-election.sh --zookeeper 10.0.3.17:2181

原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94

kafka 副本机制和容错处理 -2的更多相关文章

  1. 深入理解 Kafka 副本机制

    一.Kafka集群 二.副本机制         2.1 分区和副本         2.2 ISR机制         2.3 不完全的首领选举         2.4 最少同步副本         ...

  2. Kafka 学习之路(五)—— 深入理解Kafka副本机制

    一.Kafka集群 Kafka使用Zookeeper来维护集群成员(brokers)的信息.每个broker都有一个唯一标识broker.id,用于标识自己在集群中的身份,可以在配置文件server. ...

  3. Kafka 系列(五)—— 深入理解 Kafka 副本机制

    一.Kafka集群 Kafka 使用 Zookeeper 来维护集群成员 (brokers) 的信息.每个 broker 都有一个唯一标识 broker.id,用于标识自己在集群中的身份,可以在配置文 ...

  4. kafka副本机制之数据可靠性

    一.概述 为了提升集群的HA,Kafka从0.8版本开始引入了副本(Replica)机制,增加副本机制后,每个副本可以有多个副本,针对每个分区,都会从副本集(Assigned Replica,AR)中 ...

  5. Kafka——副本(Replica)机制

    副本定义 Kafka 是有主题概念的,而每个主题又进一步划分成若干个分区.副本的概念实际上是在分区层级下定义的,每个分区配置有若干个副本. 所谓副本(Replica),本质就是一个只能追加写消息的提交 ...

  6. Kafka 入门(二)--数据日志、副本机制和消费策略

    一.Kafka 数据日志 1.主题 Topic Topic 是逻辑概念. 主题类似于分类,也可以理解为一个消息的集合.每一条发送到 Kafka 的消息都会带上一个主题信息,表明属于哪个主题. Kafk ...

  7. 入门大数据---Kafka深入理解分区副本机制

    一.Kafka集群 Kafka 使用 Zookeeper 来维护集群成员 (brokers) 的信息.每个 broker 都有一个唯一标识 broker.id,用于标识自己在集群中的身份,可以在配置文 ...

  8. Kafka 存储机制和副本

    1.概述 Kafka 快速稳定的发展,得到越来越多开发者和使用者的青睐.它的流行得益于它底层的设计和操作简单,存储系统高效,以及充分利用磁盘顺序读写等特性,和其实时在线的业务场景.对于Kafka来说, ...

  9. Kafka副本同步机制

    引用自:http://blog.csdn.net/lizhitao/article/details/51718185 Kafka副本 Kafka中主题的每个Partition有一个预写式日志文件,每个 ...

随机推荐

  1. CodeForces 1408I Bitwise Magic

    题意 给定三个整数 \(n,k,c\) 和一个长度为 \(n\) 的序列 \(a\),保证 \(a_i\) 互不相同.可以操作 \(k\) 次,每次随机选择一个 \(a_i\) 变成 \(a_i-1\ ...

  2. GPRS DTU工作的原理与应用场景

    GPRS DTU是属于物联网无线数据终端设备的中一种,它主要是利用公用运营商的GPRS网络(又称G网)来为用户提供无线长距离数据传输的功能.一般都是采用的高性能工业级8/16/32位通信处理器和工业级 ...

  3. 使用 Xunit.DependencyInjection 改造测试项目

    使用 Xunit.DependencyInjection 改造测试项目 Intro 这篇文章拖了很长时间没写,之前也有介绍过 Xunit.DependencyInjection 这个项目,这个项目是由 ...

  4. 教你如何 分析 Android ANR 问题

    ANR介绍 ANR 的全称是 Application No Responding,即应用程序无响应,具体是一些特定的 Message (Key Dispatch.Broadcast.Service) ...

  5. Docker 基础 B站 学习 最强 教程

    狂神说!! https://www.bilibili.com/video/BV1og4y1q7M4

  6. 13、form组件

    Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否 ...

  7. leetcode99:n-queens

    题目描述 N皇后问题是把N个皇后放在一个N×N棋盘上,使皇后之间不会互相攻击. 给出一个整数n,返回n皇后问题的所有摆放方案 例如: 4皇后问题有两种摆放方案 [".Q..",  ...

  8. SQL删除语句DROP、TRUNCATE、 DELETE 的区别

    主要介绍了SQL删除语句DROP.TRUNCATE. DELETE 的区别,帮助大家更好的理解和学习sql语句,感兴趣的朋友可以了解下 DROP: 1 DROP TABLE test; 删除表test ...

  9. 最全总结 | 聊聊 Python 办公自动化之 Word(上)

    1. 前言 日常自动化办公中,使用 Python 真的能做到事半功倍! 在上一个系列中,我们对 Python 操作 Excel 进行了一次全面总结 最全总结 | 聊聊 Python 办公自动化之 Ex ...

  10. Linux Capabilities 入门教程:进阶实战篇

    原文链接:https://fuckcloudnative.io/posts/linux-capabilities-in-practice-2/ 该系列文章总共分为三篇: Linux Capabilit ...