消息消费的顺序问题
消息在被追加到 Partition 的时候都会分配一个特定的偏移量(offset),Kafka 通过偏移量(offset)来保证消息在分区内的顺序性。为了保证 Kafka 中消息消费的顺序,可以采用以下 2 种方法:
-
设置 1 个 Topic 只对应一个 Partition
破坏了 Kafka 的设计初衷,不推荐使用。
-
发送消息的时候指定 key
同一个 key 的消息可以保证只发送到同一个 Partition。
提升:如何保证消息的顺序性?
消息丢失问题
Producer 丢失数据
如果 Producer 端设置了 acks=all
,则不会丢失数据。
Leader 在所有的 Follower 都同步到了消息之后,才认为本次写成功。如果没满足这个条件,生产者会进行无限次重试。
Consumer 丢失数据
默认情况下,Kafka 会自动提交 Offset,Kafka 认为 Consumer 已经处理消息了,但是 Consumer 可能在处理消息的过程中挂掉了。重启系统后,Consumer 会根据提交的 Offset 进行消费,也就丢失了一部分数据。
解决:关闭自动提交 Offset,在处理完之后自己手动提交 Offset,就可以保证数据不会丢失。但可能会存在消息重复消费问题。
Broker 丢失数据
比较常见的一个场景:Kafka 某个Leader 所在的 Broker 宕机,需要重新选举新的 Leader ,但此时其他的 Follower 部分数据尚未同步完成,选举某个 Follower 成 Leader 后就丢失一部分数据。
所以此时一般设置如下 4 个参数:
-
Topic 设置
replication.factor
参数参数值必须大于 1,要求每个 Partition 必须有至少 2 个副本。
-
Kafka 服务端设置
min.insync.replicas
参数参数值必须大于 1,要求每个 Partition 必须有至少 2 个副本。
-
Producer 设置
acks=all
要求每条数据,必须是写入所有副本,才认为写成功。
-
Producer 端设置
retries=MAX
MAX 即是一个超级大的数字,表示无限次重试。
retries=MAX
要求一旦写入数据失败,就无限重试。
消息重复消费问题
Consumer 消费了数据后,每个一段时间,会将已消费过的消息的 Offset 进行提交,这样,重启后,可以继续从上次消费过的 Offset 来继续消费。测试时,直接 kill 进程,然后再重启后,会导致 Consumer 将有些消息处理了,但是还未来得及提交 Offset,重启后,少数消息会再消费一次。
解决:需要结合具体业务来思考,可从以下几个思路来考虑:
- 如果要将数据写入数据库中,先根据主键查查询,如果这数据已存在,就不用插入数据了。
- 向 Redis 中写入数据,可以使用 set,这样数据不会重复
- 基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束了,重复数据插入只会报错,不会导致数据库中出现脏数据。
参考:
标签:Consumer,常见,Kafka,消息,Offset,一些,数据,丢失 From: https://www.cnblogs.com/i9code/p/17988403