6.1 关于 ACK 机制
关于 ACK 机制 ,不了解的小伙伴,可以看这里:Kafka 架构深入 ,通过 ACK 机制保证消息送达。Kafka 采用的是至少一次(At least once),消息不会丢,但是可能会重复传输。
acks 的默认值即为1,代表我们的消息被leader副本接收之后就算被成功发送。我们可以配置 acks = all ,代表则所有副本都要接收到该消息之后该消息才算真正成功被发送。
6.2 关于设置分区
为了保证 leader 副本能有 follower 副本能同步消息,我们一般会为 topic 设置 replication.factor >= 3。这样就可以保证每个 分区(partition) 至少有 3 个副本,以确保消息队列的安全性。
6.3 关闭 unclean leader 选举
我们最开始也说了我们发送的消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进行同步。多个 follower 副本之间的消息同步情况不一样,当我们配置了 unclean.leader.election.enable = false 的话,当 leader 副本发生故障时就不会从 follower 副本中和 leader 同步程度达不到要求的副本中选择出 leader ,这样降低了消息丢失的可能性。
6.4 关于发送消息
为了得到更好的性能,Kafka 支持在生产者一侧进行本地buffer,也就是累积到一定的条数才发送,如果这里设置不当是会丢消息的。
生产者端设置:producer.type=async, sync,默认是 sync。
当设置为 async,会大幅提升性能,因为生产者会在本地缓冲消息,并适时批量发送。
如果对可靠性要求高,那么这里可以设置为 sync 同步发送。
一般时候我们还需要设置:min.insync.replicas> 1 ,消息至少要被写入到这么多副本才算成功,也是提升数据持久性的一个参数,与acks配合使用。
但如果出现两者相等,我们还需要设置 replication.factor = min.insync.replicas + 1 ,避免在一个副本挂掉,整个分区无法工作的情况!
6.5 Consumer 端丢失消息
consumer端丢失消息的情形比较简单:
如果在消息处理完成前就提交了offset,那么就有可能造成数据的丢失。
由于Kafka consumer默认是自动提交位移的,所以在后台提交位移前一定要保证消息被正常处理了,因此不建议采用很重的处理逻辑,如果处理耗时很长,则建议把逻辑放到另一个线程中去做。
为了避免数据丢失,现给出几点建议:设置 enable.auto.commit=false
关闭自动提交位移,在消息被完整处理之后再手动提交位移。
总结:
保证kafka消息不丢失主要是采用以下几个措施,
ACK 机制 、 设置分区、关闭 unclean leader 选举等等。