Kafka入门
Posted _TIM_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kafka入门相关的知识,希望对你有一定的参考价值。
消息队列简介
消息Message
是指在应用之间传送的数据,消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象。
消息队列Message Queue
是一种应用间的通信方式,消息发送后可以立即返回,有消息系统来确保信息的可靠专递,消息发布者只管把消息发布到MQ中而不管谁来取,消息使用者只管从MQ中取消息而不管谁发布的,这样发布者和使用者都不用知道对方的存在,常用的有RabbitMQ
,ActiveMQ
(支持消息队列当中事务处理),RocketMQ
(阿里开源的消息队列)
消息队列的模型:主要是基于发布与订阅模型,还有点对点模式
发布/订阅模式下包括三个角色:角色主题Topic
、发布者Publisher
、订阅者Subscriber
。发布者将消息发送到Topic
,系统将这些消息传递给多个订阅者
发布/订阅模式特点:
• 每个消息可以有多个订阅者;
• 发布者和订阅者之间有时间上的依赖性。针对某个主题Topic
的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息。
• 为了消费消息,订阅者需要提前订阅该角色主题,并保持在线运行;
Kafka
Kafka
是一个分布式消息发布订阅系统。Kafka
吞吐量非常高,而且消息的处理速度非常快、可扩展并且可持久化。它的分区特性,可复制和可容错都是其不错的特性。Kafka
通常用于操作监控数据(指标分析)、日志聚合解决方法、流式处理
Kafka
是一个分布式的消息队列系统,分布式就是由多个节点组成,一个节点就是一个服务器,在Kafka
当中节点叫做broker
,一个节点就是一个broker
,一个broker
就是一个服务器
Kafka的基本架构:
生产者:producer
主要负责生产数据到topic
里面去
topic: 虚拟的概念,某一类消息的主题,某一类消息都是存放在某一个topic
当中,一个topic
有多个partition
:一个partition
里面有多个segment
段,每个segment
默认1GB
一个segment: 一个.index
文件 + 一个.log
文件
.log:
存放用户真实的产生的数据
.index
存放的是.log
文件的索引数据
消费者:consumer
主要就是消费topic
里面的数据,conusmer
消费到哪一条数据需要进行记录:offset
来进行记录数据的偏移量,每条数据都有唯一的offset
**.index文件:**存放的索引文件,用于查找.log
文件里面的数据
Kafka的Partition分区:
调大分区的个数: 可以加快数据的消费的速度
**kafka当中的数据消费出现延迟:**加大消费者线程数量,加大分区的个数
Partition数量决定了每个Consumer group中并发消费者的最大数量。任意时刻,一个分区里面的数据,只能被一个消费组里面的一个线程进行消费
partition
个数 = 线程的个数 刚刚好,一个线程消费一个分区
partition
个数 > 线程的个数 有线程需要去消费多个分区里面的数据
partition
个数 < 线程的个数 有线程在闲置
Kafka的Replica
-
Kafka
的topic
可以设置有N
个副本replica
,副本数最好要小于broker
的数量,也就是要保证一个broker
上的replica
最多有一个,所以可以用broker id
指定Partition replica
。 -
创建副本的单位是
topic
的分区,每个分区有1个leader
和0到多个follower
,我们把多个replica
分为Lerder replica
和follower replica
,而follower replica
存在的唯一目的就是防止消息丢失,并不参与具体的业务逻辑的交互。 -
当
producer
在向partition
中写数据时,根据ack
机制,默认ack=1
,只会向leader
中写入数据,然后leader
中的数据会复制到其他的replica
中,follower
会周期性的启动线程从leader
中pull
数据,但是对于数据的读写操作都在leader replica
中,follower
副本只是当leader
副本挂了后才重新选取leader
。
Kafka的“同步”
kafka
不是完全同步,也不是完全异步,是一种特殊的ISR
In Sync Replica
-
leader
会维持一个与其保持同步的replica
集合,该集合就是ISR
,每一个partition
都有一个ISR
,它由leader
动态维护。 -
我们要保证
kafka
不丢失消息,就要保证ISR
这组集合存活(至少有一个存活),并且消息commit
成功。
所以我们判定存活的概念时什么呢?分布式消息系统对一个节点是否存活有这样两个条件判断:第一个,节点必须维护和zookeeper
的连接,它通过心跳机制检查每个节点的连接;第二个,如果节点时follower
,它必要能及时同步与leader
的写操作,不是延时太久。
如果满足上面2个条件,就可以说节点时“in-sync“(同步中的)。leader
会追踪”同步中的“节点,如果有节点挂了,卡了,或延时太久,那么leader
会它移除。
Kafka的数据的分区策略:
Kafka
五个分区:由于某种原因 0,1,2三个分区里面的数据太多,3,4分区里面的数据太少,如果指定了分区号,直接将数据发送到指定的分区里面去;如果没有指定分区号,数据带了发送的key
,通过key
取hashCode
决定数据究竟发送到哪一个分区里面去;如果既没有指定分区号,也没有指定数据key
,使用round-robin fashion
轮询策略
Kafka的数据消费模型:
exactly once:
消费且仅消费一次
at least once:
最少消费一次 出现数据重复消费的问题
at most once:
至多消费一次 出现数据丢失的问题
数据重复消费或者数据丢失的原因造成:offset
没有管理好
将offset
的值给保存到redis
里面去或者hbase
里面去
消息队列应用场景
消息队列在实际应用中包括如下四个场景:
应用耦合: 多应用间通过消息队列对同一消息进行处理,避免调用接口失败导致整个过程失败
异步处理:多应用对消息队列中同一消息进行处理,应用间并发处理消息,相比串行处理,减少处理时间;
限流削峰: 广泛应用于秒杀或抢购活动中,避免流量过大导致应用系统挂掉的情况;
消息驱动的系统: 系统分为消息队列、消息生产者、消息消费者,生产者负责产生消息,消费者(可能有多个)负责对消息进行处理;
kafka当中的log寻址机制 :
二分查找发,折半查找
Kafka的消息不丢失机制
总体来说就是通过保证leader partition
和至少一个follow partition
都成功写入了数据
-
生产者数据不丢失: 使用
ack
机制发送数据方式有同步和异步,生产者数据发送出去,需要服务端返回一个确认码,即ack
响应码,如果broker
端一直不给ack
状态,producer
永远不知道是否成功;producer
可以设置一个超时时间10s,超过时间认为失败 -
broker
数据不丢失: 使用副本策略形成冗余
所以此时一般是要求起码设置如下4个参数:
一、 给这个topic
设置replication.factor
参数:这个值必须大于1,要求每个partition
必须有至少2个副本
二、 在kafka
服务端设置min.insync.replicas
参数:这个值必须大于1,这个是要求一个leader
至少感知到有至少一个follower
还跟自己保持联系,没掉队,这样才能确保leader
挂了还有一个follower
三、 在producer
端设置acks=all
:这个是要求每条数据,必须是写入所有replica
之后,才能认为是写成功了
四、 在producer
端设置retries=MAX
(很大很大很大的一个值,无限次重试的意思):这个是要求一旦写入失败,就无限重试,卡在这里了
这样配置之后,至少在kafka broker
端就可以保证在leader
所在broker
发生故障,进行leader
切换时,数据不会丢失 -
消费者数据不丢失: 记录好
offset
值即可,简单offset
记录方案:每次消费时更新每个topic+partition
位置的offset
在内存中,当调用关闭consumer
线程时,把上面offset
数据记录到文件中。
唯一可能导致消费者弄丢数据的情况,就是说,你那个消费到了这个消息,然后消费者那边自动提交了offset,让kafka以为你已经消费好了这个消息,其实你刚准备处理这个消息,你还没处理,你自己就挂了,此时这条消息就丢咯。这不是一样么,大家都知道kafka会自动提交offset,那么只要关闭自动提交offset,在处理完之后自己手动提交offset,就可以保证数据不会丢。但是此时确实还是会重复消费,比如你刚处理完,还没提交offset,结果自己挂了,此时肯定会重复消费一次,自己保证幂等性就好了。
Kafka重复消费原因
- 强行
kill
线程,导致消费后的数据,offset
没有提交。 - 设置
offset
为自动提交,关闭kafka
时,如果在close
之前,调用consumer.unsubscribe()
则有可能部分offset
没提交,下次重启会重复消费。 - (重复消费最常见的原因):消费后的数据,当
offset
还没有提交时,partition
就断开连接。比如,通常会遇到消费的数据,处理很耗时,导致超过了Kafka
的session timeout
时间(0.10.x版本默认是30秒),那么就会re-blance重平衡,此时有一定几率offset
没提交,会导致重平衡后重复消费。 - 当消费者重新分配
partition
的时候,可能出现从头开始消费的情况,导致重发问题。 - 当消费者消费的速度很慢的时候,可能在一个
session
周期内还未完成,导致心跳机制检测报告出问题。
Kafka为什么读写这么快?
Kafka
数据的存储是在磁盘里面,但磁盘文件为什么能够做到速度这么快?实现每秒过万条数据可以轻松处理?
第一个原因: 使用pageCache
页缓存技术
首先Kafka是基于操作系统的页缓存来实现文件写入的。操作系统本身有一层缓存,叫做page cache,是在内存里的缓存,我们也可以称之为os cache,意思就是操作系统自己管理的缓存。你在写入磁盘文件的时候,可以直接写入这个os cache里,也就是仅仅写入内存中,接下来由操作系统自己决定什么时候把os cache里的数据真的刷入磁盘文件中。仅仅这一个步骤,就可以将磁盘文件写性能提升很多了,因为其实这里相当于是在写内存,不是在写磁盘
第二个原因: 顺序的读写磁盘,顺序的读写磁盘的速度比操作内存更快,他是以磁盘顺序写的方式来写的。也就是说,仅仅将数据追加到文件的末尾,不是在文件的随机位置来修改数据。但是如果是追加文件末尾按照顺序的方式来写数据的话,那么这种磁盘顺序写的性能基本上可以跟写内存的性能本身也是差不多的。所以Kafka
在写数据的时候,一方面基于了os
层面的page cache
来写数据,所以性能很高,本质就是在写内存罢了。另外一个,他是采用磁盘顺序写的方式,所以即使数据刷入磁盘的时候,性能也是极高的,也跟写内存是差不多的。基于上面两点,kafka就实现了写入数据的超高性能。
CAP理论
三口锅,但是只有两个锅盖,用于有一口锅盖不住
Consistency:
一致性、Availability:
可用性、Partition tolerance:
分区容错性,在分布式系统当中,这三个指标顶多只能满足其中的两个所有的分布式系统,都遵循这个CAP定律
一致性: 研究的是多个节点当中的数据是否一样
强一致性: 一旦更新之后,其他的节点可以马上感知得到
弱一致性: 一旦更新之后,其他的节点,不用更新
最终一致性: 一旦更新之后,最终所有的节点都会更细
可用性: 研究的就是服务器是否会给响应
分区容错: 研究的就是多个分区实现数据的备份机制
Kafka
满足的是CAP当中的CA:一致性和可用性 ,不满足分区容错性,kafka
当中使用ISR尽量的避免分区容错性
以上是关于Kafka入门的主要内容,如果未能解决你的问题,请参考以下文章