Kafka如何保证全链路消息不丢失,kafka如何实现高性能、高吞吐
全链路保证消息不丟失
生产端
数据丢失场景:为了提高吞吐量,生产端异步发送消息的情况下,会先存储再本地缓存中,当缓冲区大小、时间间隔到达会触发send操作,发送消息;
- 生产端宕机,会导致缓冲区的数据丢失;
- ACK策略过低;(网络因素)
方案:
- 数据一致性要求高,使用同步发送消息:最少一次的实现;
- 生产端使用Kafka事务消息;保证精准一次;
- 存储到中间介质,如:发送失败的消息转储,另外进行重试(前提实现幂等Kafka事务);或告警;
- ACK策略采用 >= 1
kakfa服务端
服务端消息丢失场景:
Kafka是异步落盘:kafka接收到消息,只要数据写入PageCache中,就会返回ACK,不需要等待落;如果pageCache落盘前宕机,会发生消息丢失的现象;概率很小;
解决:服务端保证消息可靠一般通过副本机制:
- 可用选择落盘策略,降低这两个参数,提高数据一致性:
- log.flush.interval.messages = 10000,设置多少条消息,触发一次刷盘操作;
- log.flush.interval.ms = 10000:间隔多少时间,触发刷盘;
- 增加ISR副本数:min.insync.replicas>= 2;
消费端
消息丢失场景:消费失败 + 自动提交机制,是基于一定的时间间隔,异步自动提交数据;
解决
- 使用手动提交,并且将消费逻辑和手动提交绑定在一个事务中,保证原子性;只有消费成功才提交offset;可用做到:最少一次;
- enable.auto.commit = false
- 要实现精确一次,还需保证幂等;
Kafka的高性能
1. Parition的并行消费
当消费者数量对应Partition数量,可以达到最大消费速率;
可以增加Partition数量,横向扩展并行度;
2. 生产消费批处理
批量发送 和 批量拉取极大提升吞吐量;
3. 零拷贝技术
减少数据拷贝次数,线程上下文切换次数;
- 索引文件:mmap + write;通常是消费端指定offset读取时用到;
- 消息文件:sendfile;通过索引,找到消息后,通过sendfile发送消息;
4. 顺序写/顺序读/磁盘预读
- 顺序写只需要数据写入时间,减少寻道、磁头旋转时间
- 大量利用page cache,写数据不需要真正写入磁盘;
- 读操作可以利用磁盘预读,连续读取多个页面,减少磁盘IO;
5. 高效存储:稀疏索引 + 二分搜索
二分搜索 + 稀疏索引 实现高效查询操作(通过时间戳和offset)
- 通过时间戳和offset 进行二分搜索;
- 稀疏索引:多条消息才会生成一个索引;
6. 消息压缩
消耗一定的CPU,提高网络传输效率,提高吞吐量;
- 生产端可用通过配置:compression.type = gzip对消息进行单个或批量压缩;减少数据大小;
- 生产端同样配置有压缩算法;当与生产端压缩算法相同,则不需要解压缩,并且能够用到零拷贝;
- 当压缩算法不一致,就需要对数据进行解压,再次压缩,势必需要将数据拷贝到用户空间进行处理;
- 当压缩算法一致,不需要对消息进行额外处理,
- 消费端直接拉取压缩的数据,在客户端进行解压缩;