Kafka学习笔记(5)——消息队列
消息丢失
可能发生消息丢失的环节:
- 生产者投递消息, 因为网络波动等原因, 没有发送成功;
- 消费者消费消息, 消费者未处理完消息就宕机, 消息没有成功消费;
- 分区中的Leader所在的Broker宕机, Leader的数据在同步到Follower前的这段时间内的消息丢失;
解决方案:
- 生产者: 使用带有返回值的消息发送方式, 通过callback得知消息是否发送成功, 如果发送失败进行重发;
- 消费者: 开启手动提交, 先消费消息, 再更新offset;
- Broker: 调整分区的Replica数量, 调整
acks
参数.
消息重复消费
发生重复消费的场景: 已经消费了消息, 但是offset没有提交. 产生的原因:
- 消费者消费完消息, 还没有提交offset, 消费者线程就被强制
kill
掉; - 消费者消费消息耗时过长, 超过了timeout, 与分区断开连接, 并且offset没有提交, 触发Rebalance后重复消费;
解决方案:
- 在有消费者线程的应用中, 尽量避免
kill -9
等操作; - 合理设置
max.poll.interval.ms
和max.poll.records
, 提高消费者处理消息的速度; - 对消费的接口幂等处理, 例如设置唯一id等方式达到单次和多次操作达到一样的效果.
消息顺序消费
同一个Partition内的消息能保证消费的顺序性, 但不同Partition之间不能保证顺序.
解决方案: 发送消息时指定分区, 需要顺序消费的消息发送到同一分区.
消息积压
可能产生消息积压的场景:
- 消费者宕机, 在重新启动消费者服务前, 数据量很大, 造成消息挤压;
- 解决方案1: 消费者服务重启后直接消费最新的消息, 积压的旧消息通过离线程序补漏;
- 解决方案2: 增大消费者的处理能力, 从上次提交offset处开始消费.
- Kafka分区不合理, 通常是分区太少, 导致消费能力不足;
- 解决方案: 适当增加分区数.
- Kafka消息的key不均匀, 分区数据不平衡;
- 解决方案: 生产者给key增加随机后缀, 使其均衡.
Kafka 高性能的原因
顺序写
Kafka虽然是写磁盘, 但因为顺序写, 直接追加数据到末尾, 性能极高.
零拷贝
Kafka高吞吐量的原因: 零拷贝. 主要是利用Java NIO中FileChannel的transferTo
方法.
传统IO实际经过4次文件内容复制:
- 将磁盘文件数据copy到操作系统内核buffer;
- 将内核buffer的数据copy到应用程序的buffer;
- 将应用程序buffer中的数据copy到socket buffer;
- 将socket buffer中的数据copy到网卡buffer进行网络传输.
零拷贝只有两次复制:
- 将磁盘文件数据copy到操作系统内核buffer;
- 将内核buffer的数据copy到网卡buffer进行网络传输.