Kafka入门

Posted _TIM_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kafka入门相关的知识,希望对你有一定的参考价值。

消息队列简介

消息Message是指在应用之间传送的数据,消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象。
消息队列Message Queue是一种应用间的通信方式,消息发送后可以立即返回,有消息系统来确保信息的可靠专递,消息发布者只管把消息发布到MQ中而不管谁来取,消息使用者只管从MQ中取消息而不管谁发布的,这样发布者和使用者都不用知道对方的存在,常用的有RabbitMQActiveMQ(支持消息队列当中事务处理),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

  1. Kafkatopic可以设置有N个副本replica,副本数最好要小于broker的数量,也就是要保证一个broker上的replica最多有一个,所以可以用broker id指定Partition replica

  2. 创建副本的单位是topic的分区,每个分区有1个leader和0到多个follower,我们把多个replica分为Lerder replicafollower replica,而follower replica存在的唯一目的就是防止消息丢失,并不参与具体的业务逻辑的交互。

  3. producer在向partition中写数据时,根据ack机制,默认ack=1,只会向leader中写入数据,然后leader中的数据会复制到其他的replica中,follower会周期性的启动线程从leaderpull数据,但是对于数据的读写操作都在leader replica中,follower副本只是当leader副本挂了后才重新选取leader

Kafka的“同步”

kafka不是完全同步,也不是完全异步,是一种特殊的ISR In Sync Replica

  1. leader会维持一个与其保持同步的replica集合,该集合就是ISR,每一个partition都有一个ISR,它由leader动态维护。

  2. 我们要保证kafka不丢失消息,就要保证 ISR这组集合存活(至少有一个存活),并且消息commit成功。

所以我们判定存活的概念时什么呢?分布式消息系统对一个节点是否存活有这样两个条件判断:第一个,节点必须维护和zookeeper的连接,它通过心跳机制检查每个节点的连接;第二个,如果节点时follower,它必要能及时同步与leader的写操作,不是延时太久。

如果满足上面2个条件,就可以说节点时“in-sync“(同步中的)。leader会追踪”同步中的“节点,如果有节点挂了,卡了,或延时太久,那么leader会它移除。

Kafka的数据的分区策略:

Kafka五个分区:由于某种原因 0,1,2三个分区里面的数据太多,3,4分区里面的数据太少,如果指定了分区号,直接将数据发送到指定的分区里面去;如果没有指定分区号,数据带了发送的key,通过keyhashCode决定数据究竟发送到哪一个分区里面去;如果既没有指定分区号,也没有指定数据key,使用round-robin fashion轮询策略

Kafka的数据消费模型:

exactly once:消费且仅消费一次
at least once:最少消费一次 出现数据重复消费的问题
at most once: 至多消费一次 出现数据丢失的问题
数据重复消费或者数据丢失的原因造成:offset没有管理好
offset的值给保存到redis里面去或者hbase里面去

消息队列应用场景

消息队列在实际应用中包括如下四个场景:
应用耦合: 多应用间通过消息队列对同一消息进行处理,避免调用接口失败导致整个过程失败
异步处理:多应用对消息队列中同一消息进行处理,应用间并发处理消息,相比串行处理,减少处理时间;
限流削峰: 广泛应用于秒杀或抢购活动中,避免流量过大导致应用系统挂掉的情况;
消息驱动的系统: 系统分为消息队列、消息生产者、消息消费者,生产者负责产生消息,消费者(可能有多个)负责对消息进行处理;

kafka当中的log寻址机制 :

二分查找发,折半查找

Kafka的消息不丢失机制

总体来说就是通过保证leader partition和至少一个follow partition都成功写入了数据

  1. 生产者数据不丢失: 使用ack机制发送数据方式有同步和异步,生产者数据发送出去,需要服务端返回一个确认码,即ack响应码,如果broker端一直不给ack状态,producer永远不知道是否成功;producer可以设置一个超时时间10s,超过时间认为失败

  2. 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切换时,数据不会丢失

  3. 消费者数据不丢失: 记录好offset值即可,简单offset记录方案:每次消费时更新每个topic+partition位置的offset在内存中,当调用关闭consumer线程时,把上面offset数据记录到文件中。

唯一可能导致消费者弄丢数据的情况,就是说,你那个消费到了这个消息,然后消费者那边自动提交了offset,让kafka以为你已经消费好了这个消息,其实你刚准备处理这个消息,你还没处理,你自己就挂了,此时这条消息就丢咯。这不是一样么,大家都知道kafka会自动提交offset,那么只要关闭自动提交offset,在处理完之后自己手动提交offset,就可以保证数据不会丢。但是此时确实还是会重复消费,比如你刚处理完,还没提交offset,结果自己挂了,此时肯定会重复消费一次,自己保证幂等性就好了。

Kafka重复消费原因

  1. 强行kill线程,导致消费后的数据,offset没有提交。
  2. 设置offset为自动提交,关闭kafka时,如果在close之前,调用 consumer.unsubscribe()则有可能部分offset没提交,下次重启会重复消费。
  3. (重复消费最常见的原因):消费后的数据,当offset还没有提交时,partition就断开连接。比如,通常会遇到消费的数据,处理很耗时,导致超过了Kafkasession timeout时间(0.10.x版本默认是30秒),那么就会re-blance重平衡,此时有一定几率offset没提交,会导致重平衡后重复消费。
  4. 当消费者重新分配partition的时候,可能出现从头开始消费的情况,导致重发问题。
  5. 当消费者消费的速度很慢的时候,可能在一个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入门的主要内容,如果未能解决你的问题,请参考以下文章

Kafka入门学习《一》

Kafka入门经典教程

大数据Kafka_Kafka入门教程

kafka概念入门[一]

kafka入门

Kafka从入门到实战