Kafka的消息可靠传递

Kafka提供的基础保障可以用来构建可靠的系统, 却无法保证完全可靠. 需要在可靠性和吞吐之间做取舍.

复制

Kafka的复制机制保证每个分区有多个副本, 每个副本可以作为leader或者follower的角色存在. 为了保证副本的同步, 需要做到:

Broker配置

复制因子

default.replication.factor broker级别的副本数设置, 通过这个配置来控制自动创建的topic的副本数. 为N的时候, 可以容忍失去N-1个副本, 保证topic的可读写.

脏副本的leader选举

unclean.leader.election.enable 0.11.0.0之前的版本, 默认为true; 之后的版本默认为false. 这个设置控制不同步的副本能否参与leader的选举. 如果设置为true, 当没有同步副本可用的时候, 不同步的副本会成为leader, 意味着有数据丢失. 如果设置为false, 则意味着系统会处于不可用的状态, 该部分没有leader提供服务. 需要在可用性一致性之间做取舍.

最小同步副本数

min.insync.replicas 这个设置可以作用于broker和topic级别. 假如broker数为3, 最小同步副本数为2. 当2个同步副本中的一个出现问题, 集群便不会再接受生产者的发送消息请求. 同事客户端会收到NotEnoughReplicasException. 此时, 消费者还可以继续读取存在的数据. 唯一的同步副本变成只读.

可靠系统中使用生产者

发送确认

acks 可选0, 1或者all. 设置影响吞吐和一致性.

额外的错误处理

使用生产者内置的重试是一个正确处理多种错误而不丢失消息的简单途径. 但是开发者还需要处理其他的错误, 比如:

可靠系统中使用消费者

已提交消息已提交偏移量 完全不同的两个概念, 前者是对生产者有效, 后者是对消费者有效.

重要设置

准确提交偏移量

总是提交已经处理过得消息

假如你是在循环中处理所有的消息, 并且不需要维护跨多次轮询的状态, 会比较容易实现. 可以使用自动提交, 或者在轮询循环的末尾进行偏移量提交.

提交频率是性能和系统崩溃时重复的消息数量间的取舍

一次轮询循环中可以进行多次偏移量提交, 甚至每处理一条提交一次. 或者几个轮询提交一次. 提交会有性能上的开销, 类似生产者的acks=all

保证你清楚的了解将要提交什么偏移量

常见的一个陷阱就是一次轮询循环中的偏移量提交了读到的最大偏移量, 而不是已经处理过得最大偏移量. 会导致消息丢失.

再平衡

准确处理consumer的再平衡(consumer上线或者下线). 再平衡会引起先从消费者上摘取某些分区, 然后在分配某些分区. 通过实现RebalanceListener接口来实现控制.

消费者可能需要重试

某些场景下, 暂时不提交偏移量, 下次轮询的时候会重复拉取消息. 比如数据库连接暂时不可用的情况下.

消费者可能需要维护状态

某些场景下, 需要在多个轮询间存在聚合运算.

处理长时间的处理

有些时候, 消息的处理耗时较长, 比如与其他系统交互或者进行比较复杂的运算. 某些Kafka版本的消费者, 两次轮询的间隔不能太长 (0.10.0.0之前版本的消费者没有单独的心跳进程, 是通过轮询同时达到心跳目的). 太长, 消费者则会被认为是下线, 会发生再平衡.

有且只有一次的消息投递

有些场景需要至少一次的语义(没有消息丢失); 而某些场景则需要有些只有一次的语义. 但是当前Kafka没有提供完美的有且只有一次的支持. 需要与其他系统结合一起实现, 比如使用唯一的key写入数据库或者redis等存储中.

Comments

comments powered by Disqus