Kafka/flume知识概要

本文深入探讨了Kafka和Flume两大数据处理工具,详细介绍了Kafka的架构、消息存储机制、生产者与消费者的特性和调优策略,以及Flume的组件、数据采集与Kafka的整合。Kafka利用磁盘顺序读写和零拷贝技术实现高吞吐,而Flume则提供灵活的数据采集方案。文章还涉及了数据一致性、幂等性、ZooKeeper的作用以及如何在Kafka和Flume之间做出选择。

一、Kafka

1、原理架构

kafka是一个分布式消息系统。具有高性能、持久化、多副本备份、横向扩展能力。消息保存在磁盘中,以顺序读写方式访问磁盘,避免随机读写导致性能瓶颈。生产者往队列里写消息,消费者从队列里取消息进行业务逻辑。

Kafka集群包含一个或多个服务器,服务器节点称为broker,broker存储topic的数据。broker可分为ControllerfollowerController管理集群broker的上下线,所有topic的分区副本分配和leaderPartition选举等工作

每条发布到Kafka集群的消息都有一个类别Topic,Topic像一个消息队列。Kafka分配的单位是partition,一个topic包含一个或多个partition,一个partition在磁盘上对应一个文件夹,一个partition会有多个副本,其中有且仅有一个partition作为Leader,Leader是当前负责数据的读写的partition,其他partition为flower作为备用选主。当Follower与Leader挂掉、卡住或者同步太慢,leader会把这个follower从“in sync replicas”(ISR)列表中删除,重新创建一个Follower。

offset:消费者在对应分区上已经消费的消息数(位置),kafka0.8 版本之前offset保存在zookeeper上。a0.8 版本之后offset保存在kafka集群上。

2、kafka的文件存储机制

一个topic,有多个不同的partition,每个partition为一个目录。partition命名的规则是,topic的名称加上一个序号,序号从0开始。

每一个partition目录下的文件,被平均切割成大小相等的数据文件(每一个数据文件都被称为一个段(segment file);每一个segment段消息,数量不一定相等,使得老的segment可以被快速清除。默认保留7天的数据,每次满1G后,在写入到一个新的文件中。

每一个partition只需要支持顺序读写就可以,也就是说它只会往文件的末尾追加数据,这就是顺序写的过程,生产者只会对每一个partition做数据的追加(写操作)。

在partition目录下,有两类文件,一类是以log为后缀的文件,一类是以index为后缀的文件,每一个log文件和一个index文件相对应,这一对文件就是一个segment file,也就是一个段。log文件:就是数据文件,里面存放的就是消息, index文件:是索引文件,记录元数据信息。

元数据指向,对应的数据文件(log文件)中消息的物理偏移地址。log文件达到1个G后滚动重新生成新的log文件。

kafka高效文件存储设计特点

  • Kafka把topic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。
  • 通过索引信息可以快速定位message
  • 通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。
  • 通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小。

3、producer

3.1、消息分区策略

kafka的分区策略,决定了producer生产者产生的一条消息最后会写入到topic的哪一个分区中

  • 1、指定具体的分区号, 数据就会写入到指定的分区中
producer.send(new ProducerRecord<String, String>
("test", 0,Integer.toString(i), "hello-kafka-"+i));
  • 2、不给定具体的分区号,给定key的值(key不断变化),这里使用key的 hashcode%分区数=分区号
producer.send(new ProducerRecord<String, String>
("test", Integer.toString(i), "hello-kafka-"+i));
  • 3、不给定具体的分区号,也不给对应的key,这个它会进行轮训的方式把数据写入到不同分区中
producer.send(new ProducerRecord<String, String>
("test", "hello-kafka-"+i));
  • 4、自定义分区

    • 定义一个类实现接口Partitioner
3.2、ack(acknowledgement 确认收到)
  • 1) 高可用型,配置:acks = -1(all), producer 等待 broker 的 ack,partition 的 leader 和 follower 全部落盘成功后才返回 ack。 At Least Once 语义。

优点:保证了producer端每一条消息都要成功,如果不成功并将消息缓存起来,等异常恢复后再次发送。
缺点:这样保证了高可用,但是这会导致集群的吞吐量不是很高,因为数据发送到broker之后,leader要将数据同步到fllower上,如果网络带宽、不稳定等情况时,ack响应时间会更长

  • 2) 折中型,配置:acks = 1 ,:producer 等待 broker 的 ack,partition 的 leader 落盘成功后返回 ack

优点:保证了消息的可靠性和吞吐量,是个折中的方案;缺点:性能处于2者中间

  • 3)高吞吐型,配置:acks = 0,producer 不等待 broker 的 ack。 At Most Once 语义。

优点:可以相对容忍一些数据的丢失,吞吐量大,可以接收大量请求;缺点:不知道发送的消息是否成功

3.3、Exactly Once 语义

ACK =-1(all),可保证 Producer 到 Server 之间不会丢失数据,即 At Least Once 语义。

ACK =0,可以保证生产者每条消息只会被发送一次,即 At Most Once 语义。

在 0.11 版本以前的 Kafka,对此是无能为力的,0.11 版本的 Kafka,引入了一项重大特性:幂等性

幂等性指 Producer 不论向 Server 发送多少次重复数据,Server 端都只会持久化一条。幂等性实现,其实就是将原来下游需要做的去重放在了数据上游。

幂等性结合 At Least Once 语义,就构成了 Kafka 的 Exactly Once 语义。
即:At Least Once + 幂等性 = Exactly Once

启用幂等性,只需要将 Producer 的参数中 enable.idompotence 设置为 true 即可。开启幂等性的 Producer 在 初始化的时候会被分配一个 PID,发往同一 Partition 的消息会附带 Sequence Number。而 Broker 端会对<PID, Partition, SeqNumber>做缓存,当具有相同主键的消息提交时,Broker 只 会持久化一条。

幂等性:就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
解决幂等性的方案有:

  1. mysql中设置业务ID,并设置为主键,且唯一
  2. 使用redis或者zk的分布式锁
3.4、producer消息发送原理流程

Kafka 的 Producer 发送消息采用的是异步发送的方式。

在消息发送的过程中,涉及到main 线程和 Sender 线程两个线程,以及一个线程共享变量RecordAccumulator。main 线程将消息发送给 RecordAccumulator,Sender 线程不断从 RecordAccumulator 中拉取消息发送到 Kafka broker。

main 线程中

  • 1)通过一个拦截器ProducerInterceptors,对发送的数据进行拦截,(这个功能其实没啥用)

  • 2)通过序列化器Serializer 对消息的key和value进行序列化

  • 3)通过使用分区器作用在每一条消息上,实现数据分发进行入到topic不同的分区中

RecordAccumulator 中

  • 1)RecordAccumulator收集消息,实现批量发送。( 它是一个缓冲区,可以缓存一批数据,把topic的每一个分区数据存在一个队列中,然后封装消息成一个一个的batch批次,最后实现数据分批次批量发送。)

Sender线程

  • 1)Sender线程从RecordAccumulator获取消息

  • 2)构建ClientRequest对象

  • 3)将ClientRequest交给 NetWorkClient准备发送

  • 4)NetWorkClient 将请求放入到KafkaChannel的缓存

  • 5)发送请求到kafka集群

  • 6)调用回调函数,接受到响应

3.5 、Producer 事务

Kafka 从 0.11 版本开始引入了事务支持。事务可以保证 Kafka 在 Exactly Once 语义的基础上,生产和消费可以跨分区和会话,要么全部成功,要么全部失败。

为了实现跨分区跨会话的事务,需要引入一个全局唯一的 Transaction ID,并将 Producer获得的PID 和Transaction ID 绑定。这样当Producer 重启后就可以通过正在进行的 TransactionID 获得原来的 PID。

为了管理 Transaction,Kafka 引入了一个新的组件 Transaction Coordinator。Producer 就是通过和 Transaction Coordinator 交互获得 Transaction ID 对应的任务状态。

Transaction Coordinator 还负责将事务所有写入 Kafka 的一个内部 Topic,这样即使整个服务重启,由于事务状态得到保存,进行中的事务状态可以得到恢复,从而继续进行。

3.6、调优,提升消息吞吐量
 //准备配置属性
 Properties props = new Properties();
 //kafka集群地址
 props.put("bootstrap.servers", "node01:9092,node02:9092,node03:9092");
 //acks它代表消息确认机制   // 1 0 -1 all
 props.put("acks", "all");
 //重试的次数
 props.put("retries", 0)
<think>首先,用户的问题是基于之前的引用和对话。用户提供了三个引用:[^1], [^2], [^3],这些是关于Hadoop、Kafka、Zookeeper等集群操作的指令。用户现在的问题是如何诊断在特定情况下生成数据后Topic无数据的原因。 用户的具体场景: - Hadoop102上使用模拟数据生成jar包生成数据。 - Hadoop102、Hadoop103、Hadoop104上启动服务:Hadoop102启动Zookeeper、KafkaFlume;Hadoop103和Hadoop104启动Zookeeper和Kafka。 - Hadoop103是Zookeeper的leader。 - 真机上的KafkaTool工具连接虚拟机的Zookeeper集群。 - 问题:连接后发现Topic无数据。 我需要参考用户提供的引用: - [^1]:关于删除Kafka Topic的命令。 - [^2]:启动Hadoop集群的命令。 - [^3]:启动Hadoop集群、Zookeeper、Hive、Kafka等的命令。 用户说这些引用仅供参考,不是我真正的需求;我应该参考用户上一次的问题和我的回答。但在这个对话中,这是第一次交互,所以没有之前的回答。用户说“用户上一次的问题和你的回答”,但在这个上下文,这可能是个错误。我应该基于当前问题。 我的任务是诊断为什么Topic无数据。可能的原因包括: 1. 模拟数据生成jar包没有正确生成数据。 2. Kafka服务没有正常运行。 3. Zookeeper集群配置错误。 4. Flume配置问题(如果使用了Flume)。 5. Topic创建或配置问题。 6. 网络连接问题(真机连接虚拟机)。 基于用户描述的服务启动: - Hadoop102:启动Zookeeper、KafkaFlume,并使用jar包生成数据。 - Hadoop103和Hadoop104:启动Zookeeper和Kafka。 - Hadoop103是Zookeeper leader。 Zookeeper集群应该有多个节点组成集群。标准Zookeeper集群需要奇数个节点(如3个)来选举leader。 步骤诊断: 1. **检查服务是否正常运行**:确保Zookeeper、Kafka在102、103、104上启动。 2. **检查数据生成**:确保jar包在Hadoop102上正确生成数据到Kafka。 3. **检查Topic创建**:Topic是否已经创建?如果没有,数据可能不会被存储。 4. **检查Kafka生产者**:jar包是否作为Kafka生产者运行?如果生产者配置不正确,数据不会发送到Kafka。 5. **检查Kafka消费者或工具连接**:KafkaTool连接Zookeeper后,是否能正确看到Topic?如果没有Topic,可能是Topic未创建或配置错误。 6. **检查Flume**:如果Flume用于传输数据,确保Flume配置正确,数据从源到Kafka。 7. **检查网络和配置**:真机是否能访问虚拟机的Zookeeper端口?Kafka端口是否开放?Zookeeper集群配置是否正确(zookeeper.connect参数)。 用户提到了“模拟数据生成架包”,这可能是一个自定义的jar包,用于生成模拟数据并发送到Kafka。 从引用中: - [^3]提到启动所有集群的命令:start-all.sh for Hadoop, and zookeeper services. - [^1]提到删除Topic的命令,这可能相关但不直接。 - [^2]提到启动HDFS和YARN。 但在用户的服务启动中,Hadoop102启动了Flume,其他节点没有提到Flume。 常见原因Topic无数据: - Kafka broker没有运行。 - Topic未创建。 - 生产者(jar包)没有连接正确的Kafka broker。 - Zookeeper集群未正确配置,导致Kafka无法协调。 - Flume配置错误(如果使用)。 诊断步骤建议: 1. 验证Zookeeper集群状态:使用zkCli.sh连接到Zookeeper集群,检查节点是否正常。 2. 验证Kafka服务:在每台机器上,使用jps检查Kafka进程是否运行。 3. 检查Topic列表:在任意一台机器上,使用kafka-topics.sh --list --zookeeper <zookeeper_list> 检查Topic是否创建。 4. 检查生产者日志:如果jar包生成数据,查看其日志,是否有错误。 5. 检查Kafka日志:查看Kafka broker日志,是否有错误。 6. 测试生产者:使用kafka-console-producer.sh手动发送消息,看Topic是否有数据。 7. 检查连接:确保真机能连接到虚拟机的Zookeeper端口(通常2181)和Kafka端口(9092)。 用户指定真机用KafkaTool连接Zookeeper集群后查看Topic无数据。KafkaTool连接到Zookeeper后能看到Topic元数据,但如果没有数据,可能是因为生产者没有发送数据。 所以,重点在数据生成端。 回答结构: - 保持清晰,结构化。 - 使用中文。 - 添加引用标识,如[^1]。 - 末尾生成相关问题。 生成相关问题: - 基于诊断步骤。 - 例如:如何检查Zookeeper集群状态?如何手动测试Kafka生产者?如何查看Kafka日志? 最终回答应包括: - 可能的原因列表。 - 诊断步骤。 - 解决方案建议。 - 相关问题。 </think>### Hadoop102上生成数据后Kafka Topic无数据的原因诊断 基于您的描述(Hadoop102使用模拟数据生成jar包生成数据,服务启动配置为:Hadoop102运行Zookeeper、KafkaFlume;Hadoop103和Hadoop104运行Zookeeper和Kafka,且Hadoop103为Zookeeper leader;真机KafkaTool连接Zookeeper集群后Topic无数据),我将逐步分析可能的原因并提供诊断建议。问题通常源于数据生成端、服务配置或网络连接的错误。以下是常见原因及排查步骤(参考了集群启动和数据操作的最佳实践[^3])。 #### 可能原因分析 1. **模拟数据生成jar包未正确运行**: - Jar包可能未成功发送数据到Kafka,原因包括:生产者配置错误(如broker地址、Topic名称不匹配)、数据生成逻辑故障(如代码错误或资源不足),或jar包未启动。 - 例如,如果jar包配置的Kafka broker地址指向错误节点(如未指向Hadoop102的Kafka服务),数据无法进入队列[^3]。 2. **Kafka服务配置或启动问题**: - Kafka broker未在102、103、104上正常运行:服务启动脚本错误、端口冲突(默认9092),或节点间通信故障。 - Topic未创建或配置不一致:如果Topic未提前创建或partition/replica设置错误,数据无法存储。删除Topic命令可能已误执行[^1]。 - Zookeeper集群配置错误:您提到Hadoop103为leader,但Zookeeper集群(102、103、104)需配置一致(如`zookeeper.connect`参数)。如果配置错误(如节点IP错误或选举失败),Kafka无法协调数据存储[^3]。 3. **Flume服务问题(如果使用)**: - Flume在Hadoop102上启动,但sink配置错误(如未指向Kafka Topic),或source未连接数据jar包。 - Flume日志未显示数据传输,表明数据流中断[^3]。 4. **网络连接和权限问题**: - 虚拟机到真机的防火墙或端口未开放:Zookeeper默认端口2181和Kafka端口9092需允许真机访问。 - KafkaTool连接问题:工具可能连上Zookeeper,但无法读取Kafka数据(如认证失败或代理地址错误)。 - 集群启动顺序错误:Hadoop集群(如HDFS)应先启动[^2],否则数据生成jar包可能无法访问依赖资源。 5. **日志和监控缺失**: - 服务日志未检查,隐藏了错误(如Kafka broker启动失败或生产者超时)。 #### 诊断步骤建议 逐步排查以定位问题(所有命令请在对应虚拟机执行): 1. **检查数据生成端(Hadoop102)**: - 验证jar包运行:查看jar包日志,确认数据是否生成并发送。 ```bash # 查看jar包输出日志(假设jar包名为data-generator.jar) java -jar data-generator.jar --logs ``` 如果日志显示"消息发送成功",但Topic无数据,则问题在Kafka端。 - 测试jar包手动发送:使用`kafka-console-producer.sh`模拟发送,检查Topic是否更新。 ```bash # 在Hadoop102上,发送测试消息到Topic(假设Topic名为test_topic) ./kafka-console-producer.sh --broker-list hadoop102:9092 --topic test_topic > Hello, test message ``` 然后在KafkaTool查看是否有数据。 2. **验证Kafka和Topic状态**: - 检查Topic是否创建:在任意节点(如Hadoop103)运行。 ```bash ./kafka-topics.sh --list --zookeeper hadoop102:2181,hadoop103:2181,hadoop104:2181 ``` 如果Topic未列出,需重新创建。 - 检查Kafka服务状态: ```bash # 在每台机器上运行 jps | grep Kafka ``` 确保所有节点都有`Kafka`进程。如果没有,检查启动命令(如脚本权限错误)[^3]。 3. **检查Zookeeper集群**: - 验证集群状态: ```bash # 在Hadoop103(leader)运行 ./zkCli.sh -server hadoop103:2181 ls /brokers/ids # 检查Kafka broker是否注册 ``` 输出应显示所有broker ID(如102,103,104)。如果缺失节点,检查Zookeeper配置(`conf/zoo.cfg`中的`server.x`列表)。 - 确认Hadoop103确实是leader:查看Zookeeper日志。 ```bash tail -f logs/zookeeper.log | grep LEADER ``` 4. **检查Flume配置(如果启用)**: - 确保Flume agent配置正确(source指向jar包输出,sink指向Kafka)。 ```bash # 在Hadoop102查看Flume日志 tail -f logs/flume.log ``` 如果日志显示"Append denied",可能是Topic权限问题。 5. **验证网络连接**: - 从真机测试虚拟机端口: ```bash # 在真机运行(假设虚拟机IP为192.168.1.102) telnet 192.168.1.102 2181 # Zookeeper端口 telnet 192.168.1.102 9092 # Kafka端口 ``` 如果连接失败,调整虚拟机防火墙(如`firewall-cmd --add-port=2181/tcp`)。 - 检查Kafka配置文件(`server.properties`)中`advertised.listeners`是否设置为虚拟机IP(非localhost),以便真机访问[^3]。 6. **审查集群启动顺序**: - 确保Hadoop集群先启动(参考[^2])。 ```bash # 在Hadoop102上 start-dfs.sh start-yarn.sh ``` 然后启动Zookeeper和Kafka序列(102、103、104顺序启动Zookeeper,再启动Kafka)。 #### 解决方案概要 - **优先修复**:80%的问题源于jar包生产者配置或Kafka服务未运行。检查jar包的`bootstrap.servers`参数是否设置为`hadoop102:9092`,并确认Topic存在。 - 如果Topic误删,使用引用[1]的命令重建Topic(但需谨慎,仅当必要)[^1]。 - 重启服务:停止所有服务后重新启动(Zookeeper先于Kafka)。 - 如仍无效,提供jar包日志或Kafka错误日志(`logs/server.log`)以进一步分析。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值