Kafka消息的可靠性(三)


Kafka多副本之间的数据一致性?一致性协议是什么?Kafka数据的可靠性?可靠性和可用性关系?等等都是需要我们去理解的。

消息可靠性就是确保系统在各种不同的环境下能够发生一致的行为.

ACID指的就是原子性,一致性,隔离性和持久性.

Kafka做了哪些来保证这些呢?

  • Kafka可以保证分区消息的顺序,如果使用同一个生产者往同一个分区写入消息.那么消息是有顺序的.ABCD这样写入的,读取的时候也是ABCD读取.
  • 只有当消息被写入分区的所有同步副本时(不一定写入到了磁盘),他才被认为是“已提交“的.生产者可以选择接受不同类型的确认,消息被完全提交时的确认,或者消息被写入首领副本时的确认,或者消息被发送到网络时的确认.
  • 只要还有一个副本是活跃的,那么已经提交的消息就不会丢失.
  • 消费者只能读取到已经提交的消息.

服务本身的可靠性

复制(副本)

在上面已经讲解过复制功能了,复制和分区的多副本架构是保证消息可靠性的核心.

一个滞后的副本会导致生产者和消费者变慢,因为在消息被认为已提交之前,客户端会等待所有同步副本接受消息.

一个副本不再同步了,我们就不用关心他了.它也不会影响消费者和生产者,也不会影响系统.只是在宕机时丢失数据的风险变大了,因为你少了一个副本.

副本相关概念:

  • AR:分区中的所有副本统称为AR。
  • ISR:是指与Leader副本保持同步状态的副本集合,Leader副本本身也是这个集合中的一员。
  • LEO:表示每个分区中最后一条消息的下一个位置,每个分区的副本都有自己的LEO。
  • HW:ISR中最小的LEO即为HW,俗称高水位,消费者只能拉取到HW之前的消息。
  • 副本是相对分区而言的,即副本是特定分区的副本。
  • 一个分区中包含一个或者多个副本,其中一个为Leader副本,其余为follower副本,各个副本位于不同的broker节点,只有leader副本对外提供服务,follower副本只负责数据同步(相当于备份)

查看实效的副本情况:

kafka-topics.sh --zookeeper localhost:2181 --describe --topic topic-partitions --under-replicated-partitions

实效副本:



每个副本都有一个lastCaughtUpTimeMs标示,表示最后同步时间,如果超过了设置的超时时间没有跟上Leader副本,则认为该follower为实效副本。

副本实效的原因:

follower进程被卡住了,在一段时间内没有向leader副本发起同步请求,比如频繁的FULL GC。

follower副本同步过慢,比如I/O开销过大,导致一段时间内追不上leader副本。

broker配置

broker有3个配置参数会影响Kafka消息存储的可靠性.参数配置可以在broker级别,也可用在主题级别.

复制系数

主题级别的配置参数为:replication.factor,而broker级别则为default.replication.factor,Kafka默认复制系数为3.

通过broker.rack参数来为每个broker配置所在的机架的名字.可以让broker部署到不同的集群中.这个很少用到,但是对于可靠性要求非常高的用户来说是需要的.比如北京海淀区一个机房,北京昌平区一个机房.broker集群如果在不同的机房中,那么将大大提高Kafka的可靠性.

不完全的首领选举

unclean.leader.election只能在broker级别配置.默认为true.

之前说过,当分区首领不可用时,一个同步副本会被选举为新首领.如果一在选举过程中没有数据丢失,也就是说提交的数据同时存在于所有的副本上,那么这个过程为---“完全”的首领选举.

但是如果首领不可用了, 其他副本又都是不同不的,我们该怎么办?

unclean.leader.election=true,就是允许不同步的副本成为首领---也就是不完全的选举.这样可能会面临丢失消息的风险.如果把参数设置为false,那么就需要等待原先的首领重新上线,但是可用性就降低了.

最少同步副本

在主题级别和broker级别上都有个参数:min.insync.replicas.

假如一个主题的一个分区有3个副本,将min.insync.replicas设置为2的时候,说明至少要有两个同步副本才能向分区写入数据.

如果3个副本中有2个副本不可用,那么broker就会停止接受生产者的请求,发送数据的生产者就会收到一个NotEnoughReplicasException.消费者仍然可以继续读取已有的数据.这样的配置就变成只读了.

这样做的目的是为了在不完全选举的时候,出现非预期的行为.为了从只读状态中恢复,必须让2个不可用分区中的一个重新变为可用的,比如重启,或者等待它变为同步的.

Leader Epoch 副本同步机制

生产者的可靠性

前面讲的是broker的可靠性,服务可靠了,那么发送消息者是否可靠呢?

发送确认acks

在第一篇Kafka文章中说的到spring.kafka.producer.acks参数配置

acks 参数指定了必须要有多少个分区副本收到消息,生产者才会认为消息写人是成功的。这个参数对消息丢失的可能性有重要影响.

该参数有如下选项。

  • acks=0 生产者将消息通过网络发送出去,那么就认为是成功的.消息被写入磁盘之前生产者不会等待任何来自服务器的响应。 也就是说,如果当中出现了问题(比如发送的对象无法序列化,网卡故障,分区离线,等不会收到任何错误),导致服务器没有收到消息,那么生产者就无从得知,消息也就丢失了。不过,因为生产者不需要等待服务器的响应,所以它可以以网络能够支持的最大速度发送消息,从而达到很高的吞吐量。
  • acks=1 首领在接受到消息并把它写入到分区数据文件中(不一定同步到磁盘上)时会返回确认或者错误响应.只要集群的首领节点收到消息,生产者就会收到一个来自服务器的成功响应.如果消息无法到达首领节点(比如首领节点崩溃,新的首领还没有被选举出来),生产者会收到一个错误响应,为了避免数据丢失, 生产者会重发消息.不过,如果一个没有收到消息的节点成为新首领, 消息还是会丢失.这个时候的吞吐量取决于使用者.
  • acks=all 只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应.比acks=1延时更高,但也更安全.该参数还可以配合min.insync.replicas使用,这样就可以决定在返回确定前至少有多少个副本能够收到消息.

发送重试

生产者需要处理的错误包括两部分,一部分是生产者可以自动处理的错误,一部分是需要开发者手动处理的错误.

如果是broker返回的错误,可以通过重试来解决.而broker返回的错误有包含两部分,一部分是重试能解决的,一部分是重试不能解决的.

比如返回:LEADER_NOT_AVAILABLE服务器正在选举leader,这是一个可重试的错误.

INVALID_CONFIG这个错误是无效配置,重试是无用的,这是一个不可重试的错误.

所以在生产中可以通过 spring.kafka.producer.retries:3 来设置最大重试错误次数.这里设置为3次.当收到broker返回错误时重试3次.

错误处理

这里主要是针对开发人员的错误处理.有些错误虽然重试无效,但是开发人员需要发现该错误,并且去解决的.

比如:消息大小错误,认证错误,序列化错误,消息占用的内存达到上限的错误等,这些是开发人员需要解决的错误.

消费者的可靠性

消费者行为可靠性需要注意以下4个重要参数:

1.group.id:如果2个消费者具有相同的group.id,并且订阅了同一个主题,那么一条消息只能被同一个群组里面的一个消费者消费. 如果希望两个消费者能消费同一条数据,则可以设置不同的group.id即可.

2.out.offset.reset: 在没有偏移量可提交时(比如第一次启动)或者请求的偏移量在broker不存在时,消费者会做些什么? 一种是earlist,消费者会从分区的开始位置读取数据,不管偏移量是否有效,这样会导致消费者读取大量的重复数据,但可以保证最少的数据丢失.另外一种是latest,消费者会从分区的末尾开始读取数据,这样可以减少重复处理消息,但是会错过一些消息.

3.enable.auto.commit:是否自动提交偏移量.默认配置自动提交.
4.auto.commit.interval.ms:与第3个参数有直接的关系.如果选择了自动提交偏移量,可以通过该参数配置提交的频度.默认值是5s提交一次.

注意,如果改为手动提交,消费者拉取了1-30条消息.这个时候只需要提交30即可,因为拉取数据是从偏移量最大开始拉取的.在手动提交下,如果1-30条消息,第25条处理失败了,26,27,29,30处理成功了,这个时候提交了30偏移量.那么25这条消息也会被认为已经处理成功了.如果非要提交30偏移量,可以将第25条消息保存到其他地方,稍后处理.

为什么不支持读写分离

1.网络延时问题,Kafka主从同步会进过网络-主节点内存-主节点磁盘-网络-从节点-从节点磁盘。

2.对于Kafka来说,中从并不一定能很好的负载均衡。对于鞋数据压力很大而读压力很小的情况来说,读只能分担一小部分压力。

3.其实在我个人开来,Kafka中的分区本身就能很好的实现负载均衡,所以不一定需要读写分离来完成。

4.增加读写分类使得Kafka代码逻辑变得更加复杂。

复制与分区总结

  1. 分区没有限制,但是复制的副本不能大于broker数量.
  2. 同一个broker节点中不可能出现它的多个副本.(同第一条)
  3. 如果一个任意分区leader副本不可用,那么就意味着整个分区变得不可用(Leader不可用不是会自动选择跟随副本为Leader吗?跟随副本成为Leader也是属于Leader可用,这里说的是Leader不可用了哦)
2019-12-03 12:11104