Bootstrap

Kafka优化总结、Kafka数据丢失解决方案、重复消费解决方案

一、Kafka优化总结

翻译原文如下:

https://www.infoq.com/articles/apache-kafka-best-practices-to-optimize-your-deployment

1. 设置日志配置参数以使日志易于管理

kafka 日志文档 https://kafka.apache.org/documentation/#log

kafka 压缩基础知识  https://kafka.apache.org/documentation/#design_compactionbasics

 

2. 了解 kafka 的 (低) 硬件需求

CPU :除非需要SSL和日志压缩,否则Kafka不需要强大的CPU。使用的内核越多,并行性能越好,大多数情况下压缩,压缩也不会产生影响,应该使用LZ4 编码器来提供最佳性能。

RAM:对特别重的负载生产负载,使用32GB一上的机器,将提高客户端吞吐量

磁盘:如果在RAIO设置中使用多个驱动器,就该Kafka大显身手。由于Kafka的顺序磁盘I/O范式,所有SSD不会提供太多的优势,不应该使用NAS

网络和文件系统:建议使用XFS,如果条件允许,还可以将集群放在单个数据中心。应尽量提供更多的网络带宽。

  • Apache Kafka 的基准测试:每秒 200 万次写 (在 3 台廉价的机器上)

    https://engineering.linkedin.com/kafka/benchmarking-apache-kafka-2-million-writes-second-three-cheap-machines

  • 在 AWS 上的 Apache Kafka 负载测试

    https://grey-boundary.io/load-testing-apache-kafka-on-aws/

  • 性能测试

    https://cwiki.apache.org/confluence/display/KAFKA/Performance+testing

3. 充分利用 Apache ZooKeeper

Zookeeper 节点的数量最大应该是五个。一个节点适合于开发环境,三个节点对于大多数产品Kafka集群足够了,虽然一个大型Kafka集群可能需要5个节点来减少延迟,必须考虑节点负载,近期版本的Kafka对Zookeeper的负载要低很多,早期版本使用Zookeeper来存储消费者偏移量。

为Zookeeper 提供最强大的网络带宽。使用最好的磁盘,分别存储日志、隔离Zookeeper进程、禁用交换,这些也会减少延迟。

4. 以正确的方式设置复制和冗余

5. 注意主题配置

6. 使用并行处理

7. 带着安全性思维配置和隔离 Kafka

8. 通过提高限制避免停机 Ulimit

  1. 1、创建一个新的文件:/etc/security/limits.d/nofile.conf

  2. 2、输入内容:

    • soft nofile 128000
      
      hard nofile 128000

       

  3. 3、重新启动系统或重新登录。

  4. 4、通过以下命令来验证

  5. ulimit  -a 

     

9. 保持低网络延迟

10. 利用有效的监控和警报

通过 Instaclustr 控制台中显示的 Kafka 监控图示例:监视系统指标 (如网络吞吐量、打开的文件句柄、内存、负载、磁盘使用情况和其他因素) 是必不可少的,同时还要密切关注 JVM 统计数据,包括 GC 暂停和堆使用情况。仪表板和历史回溯工具能够加速调试过程,可以提供大量的价值。与此同时,应该配置 Nagios 或 PagerDuty 等警报系统,以便在出现延迟峰值或磁盘空间不足等症状时发出警告

二、Kafka数据丢失解决方案

producer 数据不丢失:

1. 同步模式:配置=1 (只有Leader收到,-1 所有副本成功,0 不等待)Leader Partition挂了,数据就会丢失

解决:设置 -1 保证produce 写入所有副本算成功 producer.type = sync request.required.acks=-1

2. 异步模式,当缓冲区满了,如果配置为0(没有收到确认,一满就丢弃),数据立刻丢弃

解决:不限制阻塞超时时间。就是一满生产者就阻塞

producer.type = async

request.required.acks=1

queue.buffering.max.ms=5000

queue.buffering.max.messages=10000

queue.enqueue.timeout.ms = -1

batch.num.messages=200

Customer 不丢失数据

在获取kafka的消息后正准备入库(未入库),但是消费者挂了,那么如果让kafka自动去维护offset ,它就会认为这条数据已经被消费了,那么会造成数据丢失。

解决:使用kafka高级API,自己手动维护偏移量,当数据入库之后进行偏移量的更新(适用于基本数据源)

流式计算。高级数据源以kafka为例,由2种方式:receiver (开启WAL,失败可恢复) director (checkpoint保证)

流处理中的几种可靠性语义:

1. at most once  每条数据最多被处理一次(0次或1次),会出现数据丢失的问题

2. at least once 每条数据最少被处理一次(1次或更多),这个不会出现数据丢失,但是会出现数据重复

3. exactly once 每种数据只会被处理一次,没有数据丢失,没有数据重复,这种语义是大家最想实现的,也是最难实现的

但是开启WAL后,依旧存在数据丢失问题,原因是任务中断时receiver 也被强行终止了,将会造成数据丢失

在Streaming程序的最后添加代码,只有在确认所有receiver都关闭的情况下才终止程序

 

 

三、Kafka特点、优点、应用场景

1、kafka 特点

分布式:1.多分区 2. 多副本  3. 多订阅者(订阅者数量小于等于partition数量)4. 基于Zookeeper调度

高性能:1. 高吞吐量 2. 低延迟  3. 高并发 4. 时间复杂度为O(1)

持久性与扩展性:1. 数据可持久化  2. 容错性(多副本和Consumer Group 支持了容错性) 3.支持在线水平扩展(Broker 有一个或多个Partition ,Topic 有一个或多个Partition,Consumer Group 变化,我们增加了新的机器,就可以放新的topic和新的Partition)4. 消息自动平衡(消息在服务端进行平衡,consumer在消费的时候进行平衡)

Kafka 高级特性--消息事务

数据传输的事务定义:

最多一次:消息不会被重复发送、最多被传输一次、但也有可能一次不传输

最少一次:消息不会被漏发送,最少被传输一次,但也有可能重复传输(消费端需要判断处理)

精确的一次(Exactly once):不会漏传输也不会重复传输,每个消息都传输被一次而且仅仅传输一次

事务保证

Produce幂等处理、多分区原子写入(事务要保证kafka下每一分区的原子写入,原子是一个读取--处理--写入操作)

事务保证--避免僵尸实例

每个事务Producer 分配一个transactional.id ,在进程重新启动时能够识别相同的Producer实例

kafka 增加了一个与transactional.id 相关的epoch, 存储每个transactional.id 内部元数据

一旦epoch 被触发,任何具有相同的transactional.id 和更旧的epoch的Producer 被视为僵尸,Kafka会拒绝来自这些Procedure的后续事务写入

kafka高性能--零拷贝

网络传输持久性日志块(消息)

零拷贝建立在:Java Nio channel.transforTo()方法  实际是调用  Linux sendfile 系统调用

文件传输到网络的公共数据路径

1. 操作系统将数据从磁盘读入到内核空间的页缓存

2. 应用程序将数据从内核空间读入到用户空间缓存中

3. 应用程序将数据写回到内核空间到socket 缓存中

4. 操作系统将数据从socket缓冲区复制到网卡缓冲区,一便将数据经网络发出

零拷贝过程:(内核空间和用户空间零拷贝)

1.操作系统将数据从磁盘读入到内核空间的页缓存

2.将数据的位置和长度的信息的描述符增加至内核空间(socket缓存区)

3.操作系统将数据从内核拷贝到网卡缓冲区,以便将数据经网络发出

2、Kafka优点

高吞吐量、低延迟、高并发、高性能的消息中间件。Kafka 集群甚至可以做到每秒几十万、上百万的超高并发写入

页面缓存技术+磁盘顺序写+零拷贝技术

3、Kafka 应用场景

1. 消息对列

 2. 行为跟踪(用户的行为跟踪直接发送到topic ,时时处理或离线数据存储)

3. 元数据监控(操作信息运维数据监控)

4. 日志收集

5. 流处理(收集上游流数据,经过处理,发布到新的topic 中,进行处理,中间可以进行实时计算、数据处理)

6. 事件源(将状态转移作为记录,按照时间顺序的序列,我们可以回溯整个时间的变更)

7. 持久性日志(commit log ,就是说在节点之后进行一个持久性日志记录,日志可以在节点间备份一份数据,并且给故障节点间恢复提供一种机制)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

;