kafka消息的可靠性怎么保证?

Kafka架构设计:


一个topic分多个partition,多个partition可能存在于多个broker(计算机节点上),每个partition又分主从(leader+follower)

(1)对于生产者丢失数据:

(1)配置多个副本,保证数据的完整性。
leader 接收到消息,所有的 follower 都同步到了消息之后,才认为本次写成功了。如果没满足这个条件,生产者会自动不断的重试,所以在生产者方面消息可靠性较高,通过follower的消息一致性保证了写入成功性。通过 replica机制保证数据不丢,代价就是需要更多资源,尤其是磁盘资源,kafka 当前支持 GZip 和 Snappy压缩,来缓解这个问题 是否使用 replica 取决于在可靠性和资源代价之间的 balance。
(2)合理设置flush间隔。
kafka 的数据一开始就是存储在 PageCache 上的,定期 flush 到磁盘上的,也就是说,不是每个消息都被存储在磁盘了,如果出现断电或者机器故障等,PageCache 上的数据就丢。可以通过 log.flush.interval.messages 和 log.flush.interval.ms 来配置 flush 间隔,interval大,丢的数据多些,但小会影响性能。

(2)对于Kafka丢失数据:

Kafka 某个 broker 宕机,然后重新选举 partition 的 leader。若此时其他的 follower 刚好还有些数据没有同步,结果此时 leader 挂了,然后选举某个 follower 成 leader 之后,不就少了一些数据?

所以此时一般是要求起码设置如下 4 个参数:

(1)给 topic 设置 replication.factor 参数:这个值必须大于 1,要求每个 partition 必须有至少 2 个副本。
(2)在 Kafka 服务端设置 min.insync.replicas 参数:这个值必须大于 1,这个是要求一个 leader 至少感知到有至少一个 follower 还跟自己保持联系,没掉队,这样才能确保 leader 挂了还有一个 follower 吧。(ISR机制)
(3)在 producer 端设置 acks=all:这个是要求每条数据,必须是写入所有 replica 之后,才能认为是写成功了。
(4)在 producer 端设置 retries=MAX(很大很大很大的一个值,无限次重试的意思):这个是要求一旦写入失败,就无限重试

这样配置之后,至少在 Kafka broker 端就可以保证在 leader 所在 broker 发生故障,进行 leader 切换时,数据不会丢失。

(3)消费端丢失数据

(1)设置auto.commit.enable=false,Kafka 会自动提交 offset,那么只要关闭自动提交 offset,在处理完之后自己手动提交 offset,就可以保证数据不会丢,确保消息真的被消费并处理完成。但是此时确实还是可能会有重复消费,比如你刚处理完,还没提交 offset,结果自己挂了,此时肯定会重复消费一次。
那么消费者 保证不重复消费的方法:落表(主键或者唯一索引的方式,避免重复数据)。
将消费的消息选择唯一主键存储到Redis或者mongdb中,先查询是否存在,若存在则不处理;若不存在,先插入Redis或Mongdb,再进行业务逻辑处理

(2)kafka 一定要配置上消息消费失败就重试的机制

你可能感兴趣的:(中间件,kafka,java,分布式)