Kafka基本原理及常见问题

基本原理

kafka是apache开源的一个分布式、可分区、可复制的消息系统。
kafka集群中包含一个zookeeper集群,若干producer、若干consumer和若干broker(Kafka支持水平扩展,一般 broker数量越多,集群吞吐率越高)
zookeeer:管理kafka集群配置,选举leader,并在consumerGroup发生变化时进行rebalance。
producer:消息的发布者
consumer:消息的消费者
broker:中间的存储阵列
Producer 使用 push 模式将消息发布到broker,Consumer 使用pull 模式从 broker订阅并消费消息。
Producer (push) —> Broker <----(pull) Consumer

发布/订阅消息需要指定 Topic.
为了使得Kafka 的吞吐率可以线性提高,物理上把Topic 分成一个或多个Partition,每个 Partition在物理上对应一个文件夹,该文件夹下存储这个Partition 的所有消息和索引文件。创建一个 topic时,同时可以指定分区数目,分区数越多,其吞吐量也越大,但是需要的资源也越多,同时也会导致更高的不可用性,kafka 在接收到生产者发送的消息之后,会根据均衡策略将消息存储到不同的分区中。因为每条消息都被append 到该 Partition中,属于顺序写磁盘,因此效率非常高。

在 Kafka 文件存储中,同一个 topic 下有多个不同 partition,每个 partition 为一个目录,
partiton 命名规则为 topic 名称+有序序号,第一个 partiton 序号从 0 开始,序号最大值为
partitions 数量减 1。
每个 partion(目录)相当于一个巨型文件被平均分配到多个大小相等 segment(段)数据文件
中。但每个段 segment file 消息数量不一定相等,这种特性方便 old segment file 快速被删除。
默认保留 7 天的数据。
在这里插入图片描述
Segment File 由 2 大部分组成,分别为 index file 和 data file,此 2 个文件一一对应,
成对出现,后缀".index"和".log"分别表示为 segment 索引文件、数据文件

kafka的消息产生和消费过程是如何实现的:

• Broker获取消息的 start offset和size (获取消息的size大小),根据 .index 数据查找 offset 相关的 position 数据,由于 .index 并不存储所有的 offset,所以会首先查找到小于等于 start_offset 的数据, 然后定位到相应的 .log 文件,开始顺序读取到 start_offset 确定 position。
在这里插入图片描述

• 根据 position 和 size 便可确认需要读取的消息范围,根据确定的消息文件范围,直接通过 sendfile 的方式将内容发送给消费者。

Kafka怎样保证接收消息的顺序性:

保证一个分区之内消息的有序性:通过分区的概念,Kafka可以在多个consumer组并发的情况下提供较好的有序性和负载均衡。将每个分区分只分发给一个consumer组,这样一个分区就只被这个组的一个consumer消费,就可以顺序的消费这个分区的消息。因为有多个分区,依然可以在多个consumer组之间进行负载均衡。注意consumer组的数量不能多于分区的数量,也就是有多少分区就允许多少并发消费。
以上在不同的分区之间是不可以的。如果需要topic中所有消息的有序性,那就只能让这个topic只有一个分区,当然也就只有一个consumer组消费它。

如何保证kafka有且仅消费一次?kafka丢数据怎么解决?

1.消息消费的两种实现

Kafka消息消费有两个consumer接口,Low-level API和High-level API:
Low-level API:消费者自己维护offset等值,可以实现对Kafka的完全控制;
High-level API:封装了对parition和offset的管理,使用简单;
如果使用高级接口High-level API,可能存在一个问题:当消息消费者从集群中把消息取出来、并提交了新的消息offset值后,还没来得及消费就挂掉了,那么下次再消费时,之前没消费成功就楼消费了。

2.为什么会发生消息丢失和消息重复?

消息发送
Kafka消息发送有两种方式:同步(sync)和异步(async),默认是同步方式,可通过producer.type属性进行配置。Kafka通过配置request.required.acks属性来确认消息的生产
0—表示不和kafka集群进行消息接收是否成功的确认,则当网络异常、缓冲区满了等情况时,消息可能丢失;
1—表示当Leader接收成功时确认,同步模式下,只有Leader确认接收成功后但挂掉了,副本没有同步,数据可能丢失;
-1—表示Leader和Follower都接收成功时确认;

解决办法:

保证消息不丢失:
(1)同步模式下
	producer.type=sync 
	request.required.acks=1 
	消息接收确认机制设置为-1,即让消息写入Leader和Follower之后再确认消息发送成功;
(2)异步模式下
为防止缓冲区满,可以在配置文件设置:
	a.不限制阻塞超时时间,当缓冲区满时让生产者一直处于阻塞状态
			block.on.buffer.full = true;
	b.消息的数量阈值	
	
	当存有你最新一条记录的 replication 宕机的时候,Kafka 自己会选举出一个主节点,如果默认允许还未同步
最新数据的 replication 所在的节点被选举为主节点的话,你的数据将会丢失,因此这里应该按需将参数调控为 false;
	unclean.leader.election.enable = false   (默认参数为 true)
	
保证消息消费不重复:
	将消息的唯一标识保存到外部介质中,每次消费时判断是否处理过即可。

3.消息丢失解决方案:

首先对kafka进行限速, 其次启用重试机制,重试间隔时间设置长一些,最后Kafka设置acks=all,即需要相应的所有处于ISR(in-sync replica,已同步的副本)的分区都确认收到该消息后,才算发送成功。

4.消息重复解决方案

生产者(ack=all 代表至少成功发送一次)
消费者 (offset手动提交,业务逻辑成功处理后,提交offset)
消息可以使用唯一id标识
落表(主键或者唯一索引的方式,避免重复数据)
业务逻辑处理(选择唯一主键存储到Redis或者mongdb等外部介质中,先查询是否存在,若存在则不处理;若不存在,先插入Redis或Mongdb,再进行业务逻辑处理)

KafKa获取的数据如何存入hdfs?

1.可以通过flume从kafka获取数据然后存储到HDFS上
2.可以和流式计算引擎(比如spark,storm等)整合,由计算引擎写入
3.当然也可以手动代码实现

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值