Kafka可靠性保证
kafka默认的保证
- kafka的同一个生产者写入同一个分区的消息,B在A之后写入,Kafka可以确保B的偏移量B比A大,且消费者会先消费A后消费B
- 消息被所有副本(L和ISR)接受(不一定是写入磁盘)才被认为是已经被提交。
note:生产者可以选择不同类型的消息确认:
完全提交确认
写入首领确认
发送到网络确认 - 只要有一个副本活跃,提交的消息就不会丢失
- 消费者只能读取已经提交的消息。
复制机制增加的保证
复制机制和分区的多副本架构是Kafka可靠性保证的核心。
把消息写入多个副本,保证单个broker崩溃,还能购保持消息的持久性。
首领副本是同步副本,其他副本被认为是ISR的基本条件:
- 同Zookeeper有活跃session-6s正常发送一次心跳
- 10s内从L处同步过最新消息
- 10s内获取的是L的最新消息。
非ISR的副本可以在跟上同步副本的时候重新变成同步副本。
note:平凡的出现非同步副本到同步副本的切换,可能是Java的垃圾回收导致,长时间的STW。
滞后的ISR(同步慢)会影响P和C的性能:可能影响P,一定影响C,C消费的消息必须是确认后的消息。
滞后的非ISR,不会影响性能,但是会导致系统低可用,备份的机器减少。
broker配置增加的保证
## odd number is the best
## least brokers is the defined number
defalut.replication.factor:副本数目
default:3
scope:topic
## odd number is the best
replication.factor:副本数目
default:3
scope:broker
## broker最好网络隔离,电源隔离,机架隔离
broker.rack:机架的名字
unclean.leader.election:不完全选举
default:true
desc:L挂掉,非ISR可以成为首领。
不完全选举的例子
场景1:
L和两个非ISR的F
- 首先F1和F2死掉,只有L可用
- M发往L,L接受成功并且确认
- L死掉,F1和F2重启,F1当选首领
- 此时丢失M。
例子:L(两个跟随F1,F2,两个副本已经变成不同步副本了只有数据1100)写入100200,C集群已经消费了100150;L宕机,F1重启,F1变成L,此时F1新接受数据从100200(和前面的数据不同),此时C集群将会十分混乱,消费旧的(100-150)消费新的(100-200),这个时L又复活了,变成了F,他会把旧的100-200的消息全部删掉,旧的150-200就被丢掉了。
场景2:
L和两个非ISR的F
网络抖动,复制延迟,这个时候L死掉,丢失部分消息。
简单的多,允许不完全选举,就可能丢失消息;如果不允许不完全选举,降低可用性。
##最少同步副本(lsr)
min.insync.replicas:配置最少同步副本的数量
desc:
如果小于这个值,生产者会收到NotEnoughreplicasException异常,消费者还是可用从broker获取数据的。
生产者对可靠性的保证
生产者丢失消息的场景:
场景1:
- 集群有三个broker,acks=1
- L收到M,P认为MX成功;
- 消息没有同步ISR,L挂掉;
- 选举L,丢失M。
场景2:
- replica有三个,acks=all;
- L挂掉,P使用异步发送机制且没有注册监听器,重试消息丢失。
生产端开发者的注意点:
- 根据可靠性要求配置acks的值
- 在参数配置和代码里面正确处理错误。
生产者的主要配置参数
acks
重试
重试可能产生重复数据,Kafka没法保证消息只被添加一次。
我们认为失败,实际接收成功了。这样的话可能需要消费者自行处理。
额外需要处理的错误
具体包括
- 不可重试的broker错误,如果消息太大,认证错误等。
- 组装消息的时候发生的错误,如果序列化错误。
- 生产者重试达到上限,消息占用的内存太多等。
建议处理方案:
- 丢弃
- 记录错误
- 保存消息到本地硬盘
- 回调处理
消费者对可靠性的保证
- 消费者得到的M,一定具备一致性。
- 消费者总是按顺序获取数据。
消费者丢失消息,重复消费消息的主要原因
- 先提交,后消费,崩溃-----丢失消息
- 先消费,崩溃,再次消费------重复消费
消费者可靠性的配置
group.id
auto..offset.reset
enable.auto.commit
auto.commit.interval.ms
显示提交的注意点:
- 总是在处理完事件后在提交偏移量轮询内,
- 如果不需要在轮询之间维护状态,那么可以使用自动提交,或者轮询结束时手动提交
- 提交频度和重复消息之间寻找平衡点
- 提交偏移量的位置一定要注意
- 比如在事物结束后在提交偏移量。
- 再次均衡
- 分区主动退出前要提交偏移,并在分配新区的时候清理之前broker上记录的缓存信息。
- 消费者失败
- 重试:
- 提交最后成功的偏移量,
- 调用pause()方法不再继续处理消息,
- 然后轮询尝试重新处理,
- 如果轮询处理成功,或者达到最大次数,记录错误、丢弃消息,
- 调用resume()继续消费流程。
- 之后处理:遇到失败的消息,把该消息提交独立的topic,交给独立的CG进行处理。
- 消费者需要维护状态
- 例如:消费者需要计算所有消息的平均值,一批消息之前是有关系的
- 提交偏移前计算平均值,提交一个单独的topic进行维护,
- 然后重启就可以从上次的位置进行处理了。
- 但是这样也有问题,可能提交了平均值,但是没有提交偏移连,计算就会错误。
- Kafka没有提供事物机制,可以尝试使用kafkaStream类库解决问题。
- 长时间处理
- 有些数据处理时间长,但是轮询不能长时间暂停(否则没有心跳了)这种情况一种常见的方法是使用线程池处理数据,调用pause()方法保持轮询,单不获取数据,直到工作线程完成。
- 仅仅一次传递
- 将M映射到唯一的key,保存在数据库里面,消费的时候从数据库获取信息进行校验,即幂等性写入,这个是常见的模式。
验证系统可靠性
- 配置验证
- 程序验证
- 监控插件监控
配置验证