可靠性的保证
分区数据有序性
- Kafka可以保证分区中的消息时有序的,如果同一个生产者向同一个分区写入消息,消息B在消息A 之后写入,那么Kafka可以保证消息B的偏移量比消息A的大,并且消费者会先读取消息A再读取消息B
- 一条消息只有在被写入分区的所有副本时才会被认为是已提交。
- 只要还有一个副本是活动的,已提交的消息就不会丢失
- 消费者只能读取已提交的消息
复制
kafka的复制机制和分区多副本架构是kafka可靠性保证的核心。
把消息写入多个副本,可以保证kafka在发生崩溃后仍然能够提供消息的持久性。
broker层面的可靠性配置
broker
中有3个参数影响Kafka的消息存储可靠性。
参数即作用于所有topic
,也可仅作用于单个topic
复制系数
replication.factor
:主题级别的副本个数配置default.replication.factor
:broker级别,用来自动配置创建topic
时的副本数。
假设副本个数是N,那么在N-1个broker失效的情况下,客户端仍能从主题读取数据或者写入数据。所以更高的副本数,能带来更高的可用性、可靠性和更少的灾难性事故。但是会占用N倍的磁盘空间。
副本个数设置考虑因素
- 可用性:如果一个分区仅有一个副本,那么broker重启期间将不可用,副本越多,可用性越高
- 持久性:每个副本都包含了一个分区的所有数据,如果仅有一个副本,一旦磁盘损坏,分区数据就丢失了。
- 吞吐量:每增加一个副本,都会增加
broker
内复制流量。如果以10MBps的速率向一个分区发送数据,在规划集群大小时,需要考虑该因素。- 1个副本:不增加复制流量
- 2个副本:增加10MBps复制流量
- 3个副本:增加20MBps复制流量
- 端到端的延迟:每个消息,只有同步到所有副本之后,才能被消费者消费。当一个
broker
变慢,就会影响所有的客户端。 - 成本:数据副本越多,存储和网络成本就越高,所以非关键数据,副本数可以不用很高。
不彻底的首领选举
unclean.leader.election.enable
:broker
级别的配置,默认是false
当分区首领不可用时,一个同步副本会被选举为新首领,如果选举过程中未丢失数据,则成为彻底选举。
首领选举场景
- 不允许不同步副本被提升为新首领:这样配置会导致最后一个同步副本恢复前,分区是不可用的
- 允许不同步副本被提升为新首领:能够保证可用性,但是需要承担部分数据丢失和消费者读取到数据不一致的风险。
最少同步副本
min.insync.replicas
:作用在topic和broker级别
如果一个topic
有3个副本,最终只用一个同步副本,最后这个副本也变为不可用,那么需要在可用性和一致性做出选择。根据Kafka可靠性保证,一条消息被写入所有同步副本后才认为是已提交的,如果没有可用副本,则数据有可能丢失。
min.insync.replicas
:可以设置消息最少要有同步副本,才能像分区写入数据。
持久化到磁盘
消息没有被持久化到磁盘中,Kafka也可以向生产者发出确认,这取决于已经接收到晓得副本数量。我们可以配置flush.messages
用于控制同步到磁盘的最大消息数和flash.ms
用于控制同步频率。
生产者的可靠性
如果broker我们配置了高可靠,但是生产者没有进行可靠性方面的配置,那么系统还是会有丢失数据的风险。
消息确认
- acks=0:broker配置副本数是3个,但是该参数下,仅关注消息是否发送,认为发送成功就代表写入Kafka,如果broker崩溃,就是丢失消息。发送完了,在所有副本没有同步完消息前,消费者是看不到消息的。
- acks=1:首领副本写入消息后,就返回成功,与
acks=0
类似的问题,消息丢失和消费者查看数据的延迟。 - acks=all:等待所有听不副本收到消息再返回。这种最安全,在返回成功响应前会一直重试,直到消息提交成功。
生产者重试
- 可重试错误:broker本身问题,重启、首领选举等,这些再等待一段时间后就可以解决。
- 不可重试错误:序列化错误、消息过大等,这种broker无法处理,重试没有意义。
- 开发人员处理的错误:
- 消息过大、身份认证
- 序列化错误
- 重试达到上限
- 超时
消费者的可靠性
消费者的可靠性主要依赖于偏移量的提交。
涉及到reblance
时,新消费者对分区数据的消费
可靠性配置
group.id
:如果希望一个消费者消费topic
所有分区数据,则需要设置一个唯一group.id
auto.offset.reset
:指定了当没有偏移量时,消费者该如何处理earliest
:从开始位置读取,会导致重复消费latest
:从最新位置读取,会导致部分数据丢失
enable.auto.commit
:自动提交偏移量;如果业务逻辑较为复杂,需要其他程序进行提交,则需要手动提交。auto.commit.interval.ms
:控制自动提交的频率,默认每5秒提交一次。
手动提交偏移量
需要从从灵活性,正确性和性能方面进行考虑
- 总在处理完消息后提交偏移量
- 提交频率是性能和重复消息数量间的平衡
- 正确的时间点提交正确的偏移量
- 再均衡
- 消费者可能需要重试如果两个消息,#30和#31,记录#30处理失败,#31处理成功,这时不能进行#31的提交,否则会将记录#30标记为成功
运行中kafka可靠性的监控
- 消息的错误率和重试率,如果两个上升,代表系统出了问题
- 积压率:如果积压过多则代表消费者有问题,需要处理
- 收集生产者和消费者处理速率,保证二者时间差在一个合理范围。