Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【Kafka】使用Kafka,如何保证消息不丢? #8

Open
exceptionplayer opened this issue Dec 16, 2020 · 3 comments
Open

【Kafka】使用Kafka,如何保证消息不丢? #8

exceptionplayer opened this issue Dec 16, 2020 · 3 comments

Comments

@exceptionplayer
Copy link

exceptionplayer commented Dec 16, 2020

如题

@exceptionplayer
Copy link
Author

exceptionplayer commented Dec 21, 2020

Kafka

思路

一般,MQ至少包含三个组成部分,Producer,Broker,Consumer。producer发送消息到broker,consumer消费存储在Broker的消息。producer到broker,broker到consumer,broker存储消息三个环节都有可能导致消息丢失。

Kafka

Producer

丢消息场景

1、Kafka消息发送都是异步进行,所以当我们调用API发送消息之后,消息并无法保证一定会被发送到Broker,如果此时进程退出,可能导致消息丢失。
2、Kafka发送消息过程中,也可能会由于Broker异常或网络原因导致消息发送失败,如果没有相应的重试策略,也会导致消息丢失。
3、Kafka发送消息到分片的主节点,如果主节点与从节点之间没有同步成功,主节点出故障也可能导致消息丢失。

解决方案:

1、控制Kafka向Broker提交消息的时间间隔和批次大小:

batch.size:kafka在发送消息之前会按分片聚合消息,批量提交,如果该值过大,则会导致大量消息得不到及时提交,增加了延迟也增加了消息丢失风险
linger.ms:默认为0,表示不开启此选项,默认情况下消息会立马被提交。但是如果该值大于0,当消息大小没有达到batch.size时,会等待linger.ms设置的时间,也增加了延迟和消息丢失风险。

2、设置重试策略,消息发送失败后重试。重试会有消息重复的可能。
1)自动重试:设置retries。当消息发送失败后,kafka将自动重试,直到超过retries设置的重试次数。
2)手动重试:实现API提供的回调,失败后重新发送。如果设置了retries自动重试,自动重试失败之后才会回调callback,所以两者不冲突。
3、设置ack策略。

ack=0,不需要等待ack,消息写入到socket缓冲区即认为成功
ack=1,只等待主节点的ack,主节点写入本地日志即认为成功
ack=all或-1, 等待当前topic的leader节点和所有in-sync follower节点都ack才算成功。

Broker本身

丢消息场景

1、topic没有设置副本
2、in-sync副本数过少
3、broker未能及时刷盘,由于文件写入并不会立即刷新到磁盘,具体刷盘时机依赖操作系统,所以Linux系统提供了fsync来实现强制刷盘,如果没有实时刷盘,也可能导致消息丢失。
4、某些没有在in-sync状态中的节点被选成了主节点,当主节点挂掉,重新选主的过程中,如果没有在ISR中的节点被选做主节点,可能会导致消息丢失。

解决方案

1、设置topic多副本:replication.factor
2、控制核心topic的in-sync副本数量:min.insync.replicas,保证当前集群中处于正常同步状态的副本 follower 数量,当实际值小于配置值时,集群停止服务。
3、控制核心topic的刷盘间隔:log.flush.interval.messageslog.flush.interval.ms
4、禁止不在ISR中的节点被选成主节点(全局生效,无法针对topic设置):unclean.leader.election.enable

Consumer

丢消息场景

1、自动提交offset,导致消息拉取到,没有消费成功就被标记为已消费。

解决方案

1、禁止自动提交

@BreadKid
Copy link

emmmmm,
持久化数据库作backup

@exceptionplayer
Copy link
Author

对于Kafka,如果设置成ack=all,kafka性能将大幅下降,可以参考这里的一个压测数据.

@exceptionplayer exceptionplayer changed the title 使用MQ,如何保证消息不丢? 【Kafka】使用Kafka,如何保证消息不丢? Dec 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants