kafka应用分享资料.docx
- 文档编号:26405725
- 上传时间:2023-06-19
- 格式:DOCX
- 页数:21
- 大小:896.25KB
kafka应用分享资料.docx
《kafka应用分享资料.docx》由会员分享,可在线阅读,更多相关《kafka应用分享资料.docx(21页珍藏版)》请在冰豆网上搜索。
kafka应用分享资料
###Kafka的原理及使用###
1.什么是消息队列
消息是指在两个独立的系统间传递的数据,这两个系统可以是两台计算机,也可以是两个进程。
消息可以非常简单,可以是简单的字符串,也可以是保存了数据持久化的各种类型的文档集合。
队列是在消息的传输过程中的通道,是保存消息的容器,根据不同的情形,可以有先进先出,优先级队列等区别。
消息队列就是一个消息的链表。
2.为什么使用消息队列
个人觉得消息队列主要的意义是解耦和异步处理,以及在高并发场景下平滑短时间内大量的服务请求(消峰处理)。
消息队列不仅被用于系统内部组件之间的通信,同时也被用于系统跟其它服务之间的交互。
消息队列的使用可以增加系统的可扩展性、灵活性和用户体验。
非基于消息队列的系统,其运行速度取决于系统中最慢的组件的速度(注:
短板效应)。
而基于消息队列可以将系统中各组件解除耦合,这样系统就不再受最慢组件的束缚,各组件可以异步运行从而得以更快的速度完成各自的工作。
消息队列能够将业务逻辑解耦,调用方只需要下达命令而不用等待整个逻辑执行完毕。
除此之外消息队列也可以抑制性能波峰的产生,在瞬时业务增长产生时保持性能曲线的平滑。
3.使用消息队列的10个理由
1.解耦
在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。
消息队列在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。
这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
2.冗余
有时在处理数据的时候处理过程会失败。
除非数据被持久化,否则将永远丢失。
消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。
在被许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理过程明确的指出该消息已经被处理完毕,确保你的数据被安全的保存直到你使用完毕。
3.扩展性
因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的;只要另外增加处理过程即可。
不需要改变代码、不需要调节参数。
扩展就像调大电力按钮一样简单。
4.灵活性&峰值处理能力
当你的应用上了HackerNews的首页,你将发现访问流量攀升到一个不同寻常的水平。
在访问量剧增的情况下,你的应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。
使用消息队列能够使关键组件顶住增长的访问压力,而不是因为超出负荷的请求而完全崩溃。
请查看我们关于峰值处理能力的博客文章了解更多此方面的信息。
5.可恢复性
当体系的一部分组件失效,不会影响到整个系统。
消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
而这种允许重试或者延后处理请求的能力通常是造就一个略感不便的用户和一个沮丧透顶的用户之间的区别。
6.送达保证
消息队列提供的冗余机制保证了消息能被实际的处理,只要一个进程读取了该队列即可。
7.排序保证
在许多情况下,数据处理的顺序都很重要。
消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。
8.缓冲
在任何重要的系统中,都会有需要不同的处理时间的元素。
例如,加载一张图片比应用过滤器花费更少的时间。
消息队列通过一个缓冲层来帮助任务最高效率的执行--写入队列的处理会尽可能的快速,而不受从队列读的预备处理的约束。
该缓冲有助于控制和优化数据流经过系统的速度。
9.理解数据流
在一个分布式系统里,要得到一个关于用户操作会用多长时间及其原因的总体印象,是个巨大的挑战。
消息系列通过消息被处理的频率,来方便的辅助确定那些表现不佳的处理过程或领域,这些地方的数据流都不够优化。
10.异步通信
很多时候,你不想也不需要立即处理消息。
消息队列提供了异步处理机制,允许你把一个消息放入队列,但并不立即处理它。
你想向队列中放入多少消息就放多少,然后在你乐意的时候再去处理它们。
4.消息队列应用场景
以下介绍消息队列在实际应用中常用的使用场景。
异步处理,应用解耦,流量削锋和消息通讯四个场景。
4.1.异步处理
场景说明:
用户注册后,需要发注册邮件和注册短信。
传统的做法有两种1.串行的方式;2.并行方式。
a.串行方式
b.并行方式
c.使用消息队列
4.2.应用解耦
场景说明:
用户下单后,订单系统需要通知库存系统。
传统的做法是,订单系统直接调用库存系统的接口。
a.直接调用
传统模式的缺点:
1)假如库存系统无法访问,则订单减库存将失败,从而导致订单失败;
2)订单系统与库存系统耦合;
b.使用消息队列
4.3.流量削峰
场景说明:
秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。
为解决这个问题,一般需要在应用前端加入消息队列。
a.使用消息队列
1)用户的请求,服务器接收后,首先写入消息队列。
假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面;
2)秒杀业务根据消息队列中的请求信息,再做后续处理。
4.4.消息通讯
场景说明:
消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。
比如实现点对点消息通讯,或者聊天室等。
a.点对点通讯
客户端A和客户端B使用同一队列,进行消息通讯。
b.聊天室通讯
客户端A,客户端B,客户端N订阅同一主题,进行消息发布和接收。
实现类似聊天室效果。
以上实际是消息队列的两种消息模式:
点对点或发布/订阅模式。
5.Kafka是什么
Kafka是由LinkedIn开发的一个分布式的消息系统,使用Scala语言编写,用作LinkedIn的活动流(ActivityStream)和运营数据处理管道(Pipeline)的基础。
现在它已被多家不同类型的公司作为多种类型的数据管道和消息系统使用。
它以可水平扩展和高吞吐率而被广泛使用。
目前越来越多的开源分布式处理系统如Cloudera、ApacheStorm、Spark都支持与Kafka集成。
6.Kafka的设计目标
Kafka是一种分布式的,基于发布/订阅的消息系统。
主要设计目标如下:
●以时间复杂度为O
(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间复杂度的访问性能。
●高吞吐率。
即使在非常廉价的商用机器上也能做到单机支持每秒100K条以上消息的传输。
●支持KafkaServer间的消息分区,及分布式消费,同时保证每个Partition内的消息顺序传输。
●同时支持离线数据处理和实时数据处理。
●Scaleout:
支持在线水平扩展。
7.Kafka的架构
Kafka的整体架构非常简单,是显式分布式架构,producer、broker和consumer都可以有多个。
Producer,consumer实现Kafka注册的接口,数据从producer发送到broker,broker承担一个中间缓存和分发的作用。
broker分发注册到系统中的consumer。
broker的作用类似于缓存,即活跃的数据和离线处理系统之间的缓存。
客户端和服务器端的通信,是基于简单,高性能,且与编程语言无关的TCP协议。
8.kafka名词解释
8.1.topic
每条发布到kafka集群的消息属于的类别,即kafka是面向topic的。
8.2.partition
partition是物理上的概念,每个topic包含一个或多个partition。
kafka分配的单位是partition。
可通过server.properties中的num.partitions配置。
8.3.offset
Offset专指Partition以及ConsumerGroup而言,记录某个usergroup在某个partiton中当前已经消费到达的位置。
8.4.replica
Kafka支持以Partition为单位对Message进行冗余备份,每个Partition都可以配置至少1个Replication(当仅1个Replication时即仅该Partition本身)
8.5.producer
消息生产者,发布消息到kafka集群的终端或服务。
8.6.broker
kafka集群中包含的服务器。
8.7.consumer
从kafka集群中消费消息的终端或服务。
8.8.consumergroup
在high-levelconsumerAPI中,每个consumer都属于一个consumergroup,每条消息只能被consumergroup中的一个Consumer消费,但可以被多个consumergroup消费。
8.9.leader
每个Replication集合中的Partition都会选出一个唯一的Leader,所有的读写请求都由Leader处理。
其他Replicas从Leader处把数据更新同步到本地,过程类似大家熟悉的MySQL中的Binlog同步。
8.10.follower
replica中的一个角色,从leader中复制数据。
8.11.controller
Kafka集群中的其中一个Broker会被选举为Controller,主要负责Partition管理和副本状态管理,也会执行类似于重分配Partition之类的管理任务。
如果当前的Controller失败,会从其他正常的Broker中重新选举Controller。
8.12.zookeeper
kafka通过zookeeper来存储集群的meta信息,选举leader。
8.13.ISR(In-SyncReplica)
是Replicas的一个子集,表示目前Alive且与Leader能够“Catch-up”的Replicas集合。
由于读写都是首先落到Leader上,所以一般来说通过同步机制从Leader上拉取数据的Replica都会和Leader有一些延迟(包括了延迟时间和延迟条数两个维度),任意一个超过阈值都会把该Replica踢出ISR。
每个Partition都有它自己独立的ISR。
9.Kafka工作流程
1.Producer根据指定的partition方法(round-robin、hash等),将消息发布到指定topic的partition里面。
2.kafka集群接收到Producer发过来的消息后,将其持久化到硬盘,并保留消息指定时长(可配置),而不关注消息是否被消费。
3.Consumer从kafka集群pull数据(主动轮询取数据),并控制获取消息的offset。
10.Kafka消息处理机制
●producer:
Producer向Broker推送消息(push)。
●consumer:
consumer从broker拉取消息(pull)。
●push模式下很难适应不同消费速率的消费者处理消息,因为发送消息的速度是由broker决定的。
push模式的目的是为了尽快的消费,但是这样容易造成consumer来不及处理消息。
典型的表现就是网络阻塞和拒绝服务。
●pull模式可以根据消费者消费速率而抓取消息,这样避免了网络阻塞的情况发生。
11.kafka发布消息
11.1.写入方式
producer采用push模式将消息发布到broker,每条消息都被append到patition中,属于顺序写磁盘(顺序写磁盘效率比随机写内存要高,保障kafka吞吐率)。
Producer分为同步发送和异步发送,默认采用同步发送。
我们可以通过设置producer.type=async使其成为异步发送,这样我们可以批量处理请求(有利于提高吞吐率),但是这也就造成了客户端机器丢掉未发送数据的可能性。
11.2.消息路由
producer发送消息到broker时,会根据分区算法选择将其存储到哪一个partition。
11.3.写入流程
(一)producer先通过broker从zookeeper的"/brokers/.../state"节点找到该partition的leader。
(二)producer将消息发送给该leader。
(三)leader将消息写入本地log。
(四)followers从partitionleaderpull消息,写入本地log后leader发送ACK。
(五)leader收到所有ISR中的replica的ACK后,增加HW(highwatermark,最后commit的offset)并向producer发送ACK。
注:
这其中有个非常重要的参数“acks”,这个参数决定了producer要求leaderpartition收到确认的副本个数,如果acks设置数量为0,表示producer不会等待broker的响应,所以,producer无法知道消息是否发送成功,这样有可能会导致数据丢失,但同时,acks值为0会得到最大的系统吞吐量。
若acks设置为1,表示producer会在leaderpartition收到消息时得到broker的一个确认,这样会有更好的可靠性,因为客户端会等待直到broker确认收到消息。
若设置为-1,producer会在所有备份的partition收到消息时得到broker的确认,这个设置可以得到最高的可靠性保证。
Producer的确认机制配置项request.required.acks
12.kafka存储消息
kafka的消息数据存储在broker上,具体存储在partition的文件夹中。
12.1.存储方式
物理上把topic分成一个或多个patition(默认创建partition创建数量对应server.properties中的num.partitions配置),每个patition物理上对应一个文件夹,该文件夹存储该patition的所有消息和索引文件。
1)Partition文件
以上图片是基于kafka0.10.1版本的Partition文件的组成:
.index文件、.log文件以及.timeindex文件,此三个文件组成一个逻辑segment,因此可以看出一个partition由多个逻辑segment组成。
具体文件说明如下:
●.index文件为索引文件,命名规则为从0开始到,后续的由上一个文件的最大的offset偏移量来开头(19位数字字符长度)。
●.log文件为数据文件,存放具体消息数据。
●.timeindex文件的格式与.index文件格式一样,所记录的东西是消息发布时间与offset的稀疏索引,用于消息定期删除使用。
2)索引和消息文件
索引文件存储大量元数据,数据文件存储大量消息,索引文件中元数据指向对应数据文件中message的物理偏移地址。
其中以索引文件中元数据3,497为例,依次在数据文件中表示第3个message(在全局partiton表示第368772个message)、以及该消息的物理偏移地址为497。
3)消息数据文件
12.2.存储策略
无论消息是否被消费,kafka都会保留所有消息。
有两种策略可以删除旧数据:
1.基于时间:
log.retention.hours=168
2.基于大小:
log.retention.bytes=1073741824
需要注意的是,因为Kafka读取特定消息的时间复杂度为O
(1),即与文件大小无关,所以这里删除过期文件与提高Kafka性能无关。
Kafka0.10.1数据保存策略配置如下:
13.Kafka消费消息
13.1.消费API接口
Kafka采用pull方式获取消息。
kafka提供了两套consumerAPI:
a.Thehigh-levelConsumerAPI
b.TheSimpleConsumerAPI
其中high-levelconsumerAPI提供了一个从kafka消费数据的高层抽象,而SimpleConsumerAPI则需要开发人员更多地关注细节。
13.1.1.Thehigh-levelconsumerAPI
high-levelconsumerAPI提供了consumergroup的语义,一个消息只能被group内的一个consumer所消费,且consumer消费消息时不关注offset,最后一个offset由zookeeper保存。
使用high-levelconsumerAPI可以是多线程的应用,应当注意:
1.如果消费线程大于patition数量,则有些线程将收不到消息
2.如果patition数量大于线程数,则有些线程多收到多个patition的消息
3.如果一个线程消费多个patition,则无法保证你收到的消息的顺序,而一个patition内的消息是有序的
13.1.2.TheSimpleConsumerAPI
如果你想要对patition有更多的控制权,那就应该使用SimpleConsumerAPI,比如:
1.多次读取一个消息
2.只消费一个patition中的部分消息
3.使用事务来保证一个消息仅被消费一次
但是使用此API时,partition、offset、broker、leader等对你不再透明,需要自己去管理。
你需要做大量的额外工作:
1.必须在应用程序中跟踪offset,从而确定下一条应该消费哪条消息。
2.应用程序需要通过程序获知每个Partition的leader是谁。
3.需要处理leader的变更。
使用SimpleConsumerAPI的一般流程如下:
1.查找到一个“活着”的broker,并且找出每个partition的leader。
2.找出每个partition的follower。
3.定义好请求,该请求应该能描述应用程序需要哪些数据。
4.fetch数据。
5.识别leader的变化,并对之作出必要的响应。
13.2.消费方式(高级API)
consumer采用pull模式从broker中读取数据。
push模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的。
它的目标是尽可能以最快速度传递消息,但是这样很容易造成consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。
而pull模式则可以根据consumer的消费能力以适当的速率消费消息。
对于Kafka而言,pull模式更合适,它可简化broker的设计,consumer可自主控制消费消息的速率,同时consumer可以自己控制消费方式——即可批量消费也可逐条消费,同时还能选择不同的提交方式从而实现不同的传输语义。
Kafka保证的是稳定状态下每一个consumer实例只会消费某一个或多个特定partition的数据,而某个partition的数据只会被某一个特定的consumer实例所消费。
13.3.确认机制(高级API)
如果将consumer设置为autocommit,consumer一旦读到数据立即自动commit。
如果只讨论这一读取消息的过程,那Kafka确保了Exactlyonce。
但实际使用中应用程序并非在consumer读取完数据就结束了,而是要进行进一步处理,而数据处理与commit的顺序在很大程度上决定了consumerdeliveryguarantee:
1.读完消息先commit再处理消息。
这种模式下,如果consumer在commit后还没来得及处理消息就crash了,下次重新开始工作后就无法读到刚刚已提交而未处理的消息,这就对应于Atmostonce
2.读完消息先处理再commit。
这种模式下,如果在处理完消息之后commit之前consumercrash了,下次重新开始工作时还会处理刚刚未commit的消息,实际上该消息已经被处理过了。
这就对应于Atleastonce。
3.如果一定要做到Exactlyonce,就需要协调offset和实际操作的输出。
精典的做法是引入两阶段提交。
如果能让offset和操作输入存在同一个地方,会更简洁和通用。
这种方式可能更好,因为许多输出系统可能不支持两阶段提交。
比如,consumer拿到数据后可能把数据放到HDFS,如果把最新的offset和数据本身一起写到HDFS,那就可以保证数据的输出和offset的更新要么都完成,要么都不完成,间接实现Exactlyonce。
(目前就high-levelAPI而言,offset是存于Zookeeper中的,无法存于HDFS,而SimpleConsuemrAPI的offset是由自己去维护的,可以将之存于HDFS中)。
14.Kafka的HA机制
14.1.Partitionreplication(分区复制)
同一个partition可能会有多个replica(对应server.properties配置中的default.replication.factor=N)。
没有replica的情况下,一旦broker宕机,其上所有patition的数据都不可被消费,同时producer也不能再将数据存于其上的patition。
引入replication之后,同一个partition可能会有多个replica,而这时需要在这些replica之间选出一个leader,producer和consumer只与这个leader交互,其它replica作为follower从leader中复制数据。
14.2.Partitionleaderfailover(主分区故障切换)
当partition对应的leader宕机时,需要从follower中选举出新leader。
在选举新leader时,一个基本的原则是,新的leader必须拥有旧leadercommit过的所有消息。
kafka在zookeeper中(/brokers/.../state)动态维护了一个ISR(in-syncreplicas),只有ISR里面的成员才能选为leader。
对于f+1个replica,一个partition可以在容忍f个replica失效的情况下保证消息不丢失。
当所有replica都不工作时,有两种可行的方案:
1.等待ISR中的任一个replica活过来,并选它作为leader。
可保障数据不丢失,但时间可能相对较长。
2.选择第一个活过来的replica(不一定是ISR成员)作为leader。
无法保障数据不丢失,但相对不可用时间较短。
kafka0.8.*使用第二种方式。
kafka通过Controller来选举leader。
14.3.Brokerfailover(节点故障切换)
1.controller在zookeeper的/brokers/ids/[brokerId]节点注册Watche
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- kafka 应用 分享 资料