
本文共 4265 字,大约阅读时间需要 14 分钟。
深入理解Kafka系列(五)--Kafka可靠的数据传递
系列文章目录
前言
本系列是我通读《Kafka权威指南》这本书做的笔录和思考。
正文
本文主要从Kafka的可靠传输方面来进行讲解
可靠性保证和复制
数据库有数据库的可靠,如Mysql的ACID就保证了事务特性。那么Kafka也有对应的保证。从这么几个方面来保证:
- Kafka保证分区消息的顺序。 若消息B在消息A之后写入,那么Kafka会保证消息B的偏移量比A大,并且消费者会先读取消息A再读取B。
- 只有当消息被写入分区的所有同步副本时(不一定要写入磁盘),他才被认定是”已提交“的。 生产者选择不同的确认机制,acks。
- 只要有一个副本是活跃的,那么已经提交的消息就不会丢失。
- 消费者只能读取已经提交的消息。
- 所有请求只能从主副本中流入流出,从副本的只起着数据备份的作用。
以上这些基本的保证机制可以用来构建一个可靠的系统,但是仅仅依赖他们是无法保证完全可靠的,接下来就根据Kafka的复制机制以及重要的配置参数来探讨Kafka的可靠性。
Kafka的复制机制和分区的多副本架构就是Kafka可靠性保证的核心。这里再来简单的回顾下。
- Kafka的主题会被分为多个分区,而分区是基本的数据块。
- Kafka保证分区里的消息是有序的。
- 每个分区可以有多个副本,其中只有一个副本为主副本,其他副本为从副本。
- 主副本负责处理请求,从副本只负责与主副本保持同步,当首领副本不可用时,从副本选举顶替。
- 分区首领是同步副本,需要满足以下3个条件。
1.与zookeeper之间有一个活跃的会话。
2.过去10s内从首领那边获取过信息。
3.过去10s内获取的信息为最新的。
可靠系统中的broker
broker当中有3个比较重要的参数会影响kafka消息存储的可靠性,这里就从这3个参数配置方面来讲解。
复制系数
主题级别的配置参数:replication.factor
broker级别:default.replication.factor
Kafka的默认复制系数为3,也就是说,每个分区总共会被3个不同的broker复制3次。如果复制系数为N,那么即使在N-1个broker失效的情况下,仍然能够从主题读取数据或者写入数据,所以复制系数越高,可用性可靠性越好。 但是也会有缺点,复制系数为N的话,至少需要N个broker,N个数据副本,占用N倍的磁盘空间。N越大,开销越大。
如果说因为broker重启导致topic不可用的情况可以接受,那么复制系数为1即可。
如果说复制系数为2,意味着可以容忍1个broker失效,但是复制系数为2的话,可能因为重启问题导致集群不可用。
因此复制系数一般为3就够了。
首领选举
参数:unclean.leader.election在broker级别上进行配置。默认为true,意思是:当分区首领不可用时,一个同步副本会被选为新首领,如果在选举过程中没有丢失数据,也就是说提交的数据同时存在于所有同步副本上,那么这个选举称作为完全的。如果该参数为true,则允许不同步的副本成为首领,即不完全的选举。
如果说不同步的副本不能被提升为新的首领,那么分区在旧首领回复之前都是不可用的,可能会出现长时间集群不可用的情况。可靠性下来了。
如果说不同步的副本可以被提升为新的首领,那么这个副本变为不同步之后写入旧首领的消息会全部丢失, 导致数据不一致性。
简而言之就是,如果说一个系统对高可用要求比较大,可以接受一定程度的数据不一致性,那么请把这个参数设置为true。否则,对于一些对数据一致性要求较高的系统,如银行,会把这个参数设置为false。
最少同步副本
参数(主题和broker级别都是该名称):min.insync.replicas
首先,再说明一次Kafka对可靠性保证的定义:消息只有在被写入到所有同步副本之后才被认为是已提交的。 而这个参数指定了最小同步副本的个数。
1.如果说该值设置为1,那代表只要有一个同步副本,就认为消息已提交,但是如果说唯一的同步副本挂了,那么机能也就停止了。
2.如果说同步副本的个数低于该配置指定的个数,那么尝试发送消息的生产者会受到一个NotEnoughReplicasException异常。
3.当然,消费者仍然可以读取已有的数据,出现2这种情况的时候,必须要让一些不可用的分区进行恢复,比如broker重启,并等待他为同步的。
很明显,以上3种参数对kafka的可靠传输有着重大的影响。不过,在broker层面上进行配置,提高可靠性还不够,还需要从生产者消费者两个方面来进行可靠配置。
可靠系统中的生产者
首先从生产者的发送模式来细说;
- acks=0
意味着如果生产者能够通过网路把消息发送出去,那么就认定消息已经写入kafka成功。
问题是,这种模式下,发生错误的可能性是很高的,因为你一旦发送了个消息,比如java里面的对象,但是在传输过程中,对象肯定是要经过序列化的呀,如果序列化失败或者网卡发生故障,岂不是发送失败。
一般,acks=0这种模式都是用来基准测试的,因为这种模式下,高吞吐量和宽带利用率,一句话:用速度牺牲了准确率。
- acks=1
意味着首领在收到消息并把它写入分区数据文件时会返回确认或者错误响应。这个模式比acks=0的消息可靠性要高。该模式下,如果发生正常的首领选举(即原首领崩溃,剩下的同步跟随者副本开始选举出新的首领副本),生产者在选举的时候会收到相关的异常,那么如果生产者能够正确的处理这个错误,他会重试发送消息。 ,最终消息会到达新的首领那。
但是这种模式也可能会丢失数据,比如消息已经成功写入首领,但是在消息被复制到跟随者副本之前首领发生崩溃。
- acks=all
意味着首领再返回确认或者错误响应之前,会等待所有同步副本都会收到消息。当然,建议acks=all的时候,与配置min.insync.replicas结合起来,这样可以决定在返回确认前至少有多少个副本能够收到消息。
好处:这是最保险的做法。
坏处:吞吐量最慢。
其次从生产者的重试参数角度来说:
一般来说,如果broker发送错误,那么返回的错误是可以通过重试来解决的,生产者需要处理的错误包含两个部分
- 生产者可以自动处理的错误:LEADER_NOT_AVAILABLE(由broker返回)
- 需要开发者手动处理的错误(生产者不能自动处理):INVALID_CONFIG(由broker返回)
这里建议:
1.如果想抓住异常并在多尝试几次:重试次数设置的大一点。
2.如果想直接丢弃消息:重试次数第一点。
3.如果想把消息保存到某个地方然后回过头来继续处理:可以停止重试。
Kafka的跨数据中心复制工具MirrorMaker默认会进行无限制的重试。
当然,重试发送一个已经失败的消息也会带来一些风险,例如生产者因为网络问题没有收到broker的确认,但是实际上消息已经发送成功了,然后生产者重试一次,又发送成功了,那就等于broker会收到两个相同的消息。那怎么办?
答:可以尝试在消息里加入唯一标识符,用于检测重复消息,消费者在读取消息的时候可以对他们进行清理。保证消息的幂等性。
小总结
对于生产者的可靠性,如果真的要做到系统的高可靠传输,可以合理的设置acks=all,并且设置最小同步副本的个数,同时还要处理一些系统不能自动处理的错误,例如:消息大小错误、认证错误、序列化错误、生产者达到重试次数上限或者消息占用内存达到上限等错误。那么这些错误都需要程序员从代码层面来解决。
可靠系统中的消费者
讲完如何在保证Kafka可靠性的前提下生产数据后,现在看看如何同样的去读取数据。从前面的文章我们可以看到,只有那些被提交到kafka的数据,也就是被写入所有同步副本的数据,对消费者才是可用的。这意味着消费者得到的消息已经具备了一致性。
那作为消费者端,要做什么?
答:唯一要做的是跟踪哪些消息是已经读取过的,哪些是还没有读取过的。
而这样的跟踪离不开一个概念:偏移量。而消费者有这么几个参数非常的重要,与可靠性相关并且与偏移量挂钩。
- group.id
若两个消费者具有相同的group.id,并且订阅了同一个主题,那么每个消费者都会分到主题分区的一个子集,就是说他们只能读到所有消息的一个子集。
- auto.offset.reset
1.该属性指定了消费者在读取一个没有偏移量的分区或者偏移量无效的情况下该如何处理。一共有两个值
latest:在偏移量无效的时候,消费者将从最新的记录开始读取数据。
earliest:在偏移量无效的时候,消费者将从起始位置开始读取分区记录。
- enable.auto.commit
1.该属性指定了消费者是否自动提交偏移量,默认true。
2.自动提交的主要缺点就是:无法控制重复处理消息,而且,如果把消息交给另外一个后台线程去处理,自动提交机制可能会在消息还没有处理完毕就提交偏移量。
3.为了尽量避免出现重复数据或者数据丢失(本质其实就是offset没有提交或者提交两次),我们可以把它设置为false。
- auto.commit.interval.ms
如果配置3选择了true,那么可以通过该参数配置自动提交的频率,默认是5s提交一次。
讲完消费者的几个重要配置参数后,接下来再手动提交偏移量角度来说,这里说明几个需要注意的点。
- 总是在处理完时间后在提交偏移量。
- 提交频度是性能和重复消息数量之间的权衡。
- 确保对提交的偏移量有数。
- 考虑消费者再均衡的问题。(消费者增加or减少时会发生再均衡)
- 保证消息的幂等性。如借助支持为一键的系统,关系型数据库、ES、键值存储引擎等。可以使用主题+分区+偏移量的组合来创建唯一的键。换句话说,这种组合可以唯一标识一个Kafka记录
总结
其实本篇文章,本质上实在前几篇文章的基础上做一个小总结,从Kafka的broker端,生产消费端3个层面,把几个重要的点或者参数提出来,与Kafka的可靠性进行关联。
如
- Kafka的broker端:复制系数、最小同步副本数、是否完全选举。
- Kafka的生产者端:acks的影响、重试次数、哪些错误是需要代码上解决。
- Kafka的消费者端:偏移量的有关配置、偏移量提交方式、消费者的重试问题、如何保证幂等性等。
下一篇文章准备从Kafka的数据管道(连接器Connect)来写。
发表评论
最新留言
关于作者
