强大的分布式消息中间件——kafka

在我们大量使用分布式数据库、分布式计算集群的时候,是否会遇到这样的一些问题:


l  我想分析一下用户行为(pageviews),以便我能设计出更好的广告位

l  我想对用户的搜索关键词进行统计,分析出当前的流行趋势。这个很有意思,在经济学上有个长裙理论,就是说,如果长裙的销量高了,说明经济不景气了,因为姑娘们没钱买各种丝袜了。

l  有些数据,我觉得存数据库浪费,直接存硬盘又怕到时候操作效率低。

这个时候,我们就可以用到分布式消息系统了。虽然上面的描述更偏向于一个日志系统,但确实kafka在实际应用中被大量的用于日志系统。

首先我们要明白什么是消息系统,在kafka官网上对kafka的定义叫:A distributed publish-subscribe messaging system。publish-subscribe是发布和订阅的意思,所以更准确的说kafka是一个消息订阅和发布的系统。publish-subscribe这个概念很重要,因为kafka的设计理念就可以从这里说起。

我们将消息的发布(publish)暂时称作producer,将消息的订阅(subscribe)表述为consumer,将中间的存储阵列称作broker,这样我们就可以大致描绘出这样一个场面:


生产者(蓝色,蓝领么,总是辛苦点儿)将数据生产出来,丢给broker进行存储,消费者需要消费数据了,就从broker中去拿出数据来,然后完成一系列对数据的处理。

乍一看这也太简单了,不是说了它是分布式么,难道把producer、broker和consumer放在三台不同的机器上就算是分布式了么。我们看kafka官方给出的图:


多个broker协同合作,producer和consumer部署在各个业务逻辑中被频繁的调用,三者通过zookeeper管理协调请求和转发。这样一个高性能的分布式消息发布与订阅系统就完成了。图上有个细节需要注意,producer到broker的过程是push,也就是有数据就推送到broker,而consumer到broker的过程是pull,是通过consumer主动去拉数据的,而不是broker把数据主动发送到consumer端的。

这样一个系统到底哪里体现出了它的高性能,如官网上所述,翻译如下:

(1)数据在磁盘上存取代价为O(1)。一般数据在磁盘上是使用BTree存储的,存取代价为O(lgn)。
(2)高吞吐率。即使在普通的节点上每秒钟也能处理成百上千的message。
(3)显式分布式,即所有的producer、broker和consumer都会有多个,均为分布式的。
(4)支持数据并行加载到Hadoop中。
等等

至此你应该对kafka是一个什么样的系统有所体会,并能了解他的基本结构,还有就是他能用来做什么。那么接下来,我们再回到producer、consumer、broker以及zookeeper这四者的关系中来。



我们看上面的图,我们把broker的数量减少,只有一台。现在假设我们按照上图进行部署:

l  Server-1 broker其实就是kafka的server,因为producer和consumer都要去连它。Broker主要还是做存储用。

l  Server-2是zookeeper的server端,zookeeper的具体作用你可以去官网查,在这里你可以先想象,它维持了一张表,记录了各个节点的IP、端口等信息(以后还会讲到,它里面还存了kafka的相关信息)。

l  Server-3、4、5他们的共同之处就是都配置了zkClient,更明确的说,就是运行前必须配置zookeeper的地址,道理也很简单,这之间的连接都是需要zookeeper来进行分发的。

l  Server-1和Server-2的关系,他们可以放在一台机器上,也可以分开放,zookeeper也可以配集群。目的是防止某一台挂了。

简单说下整个系统运行的顺序:

1.         启动zookeeper的server

2.         启动kafka的server

3.         Producer如果生产了数据,会先通过zookeeper找到broker,然后将数据存放进broker

4.         Consumer如果要消费数据,会先通过zookeeper找对应的broker,然后消费


Kafka核心组件详解
一、Kafka发布订阅消息系统基础
     Kafka 是分布式发布-订阅消息系统。它最初由 LinkedIn 公司开发,使用 Scala语言编写,之后成为 Apache 顶级项目框架。Kafka 是一个分布式的,可划分的,多订阅者,冗余备份的持久性的服务。
     在Kafka生态架构实战中已经介绍了Kafka生态系统,伴随大数据计算,kafka作为重要的数据缓冲者,将flume收集的数据缓冲,提供给storm进行实时计算。同于storm框架,针对实时性、流式计算系统也是kafka的主要应用。它主要用于处理活跃的流式数据。
二、Kafka的特点
1、同时为发布和订阅提供高吞吐量。统计Kafka 每秒可以生产约 25 万消息(50 MB),每秒处理 55 万消息(110 MB)。
2、可持久化操作。将消息持久化到磁盘,因此可用于批量消费,通过将数据持久化到硬盘以及 replication 防止数据丢失。
3、分布式系统,易于向外扩展。所有的 producer、broker 和 consumer 都会有多个,均为分布式的。无需停机即可扩展机器。
4、kafka每个实例(broker)是无状态的,只管消息的增减,不管谁来消费,消息被处理的状态是由consumer主动从topic分区中pull消息,也就是说消息由谁消费由 consumer 决定,而不是由 server的broker决定。
三、Kafka性能测试 

     数据大量堆积导致broker卡死,这里就将使用到topic的分区,分散broker中的日志存储大小。
四、Kafka核心
1、Kafka核心组件
     Producer:消息的生产者
     Consumer:特指消息的消费者
     Consumer Group:消费者组,可以并行消费Topic中partition的消息
     Broker:缓存代理,Kafa 集群中的一台或多台服务器统称为 broker。
     Topic:特指 Kafka 处理的消息源(feeds of messages)的不同分类。
     Partition:Topic 物理上的分组,一个 topic 可以分为多个 partition,每个 partition 是一个有序的队列。partition 中的每条消息都会被分配一个有序的 id(offset)。          Message:消息,是通信的基本单位,每个 producer 可以向一个 topic(主题)发布一些消息。
     Producers:消息和数据生产者,向 Kafka 的一个 topic 发布消息的过程
     Consumers:消息和数据消费者,订阅 topics 并处理其发布的消息的过程
2、Kafka消息流程

(1)消息生产者Producer将消息发送到kafka broker 的Topic中(每个topic中有多个消息)
(2)每个topic中消息增多,topic中的消息进行分区,使得consumer可快速定位消费消息,也可同时消费多个分区中的数据,提高了传输速率。
(3)Consumer Group:消费者组里有多个消费者,每个消费者对应着不同partition分区中的数据处理。例如partition1的数据给Consumer 1,2给2,使得多个分区组成的topic由group中的多个consumer消费,也就是数据内部对相同message的并发处理。
3、核心组件分析
Producers
(1)消息生产者向kafka的一个topic中分布消息的过程kafka称为Producers
(2)变相的负载均衡:把消息发给topic的哪个partition里,实现对消息的均衡分发
(3)批量异步发送:producer和broker 两端(消息的客户端和服务端),不在一台服务器中,如果每产生一条消息就进行发送,建立一次网络连接,势必影响效率。Kafka的消息发送过程采取批量,异步发送。
Broker
(1)支持消息持久化:Broker没有副本备份,但kafka将消息进行持久化操作,以免丢失。当Consumer到kafka的broker中获取数据时,broker不会直接给consumer消费,而是把数据先保存到broker本地日志文件中(具体路径可配),每个Partition都会有一个log文件。另外日志的添加采用追加方式进行持久化,达到一个消息有序持久化效果。写入日志文件:缓存到一定阈值之后,再读写磁盘进行IO操作,提高性能
(2)谁消费了message,由消费者确定和维护这类信息(具体有zookeeper记录维护),broker不保存。
(5)消费时发生故障,kafka可快速定位到故障时没消费的那条数据。 consumer如何确定哪些消息是它没有消费的?zk来记录哪条消息消费情况,如何快速的找到没有消费的消息就涉及到kafka的稀疏索引机制。接下来再继续研究。
Messge
消息的3个属性:
(1)Offset  偏移量   消息的唯一标识,通过该标识找到消息。
(2)MessageSize 消息大小
(3)data   消息本身
Partition
分区的目的:
(1)减缓日志文件占用磁盘空间
大量消息,broker都要持久化到文件中,硬盘占用空间增大。分区将消息颗粒细分,每个partition可以存放在不同的硬盘空间中,避免单个broker中的topic文件侵占内存空间
(2)不同的consumer同时处理partition中的数据
Kafka中consumer与partition为 1:n的关系,即1个分区仅由1个消费者消费;1个消费者可以同时消费多个不同分区。分区细化消息粒度,消费者同时处理多个分区的越多,达到高效的消息并发处理。

kafka简介
Kafka是分布式发布-订阅消息系统。它最初由LinkedIn公司开发,之后成为Apache项目的一部分。Kafka是一个分布式的,可划分的,冗余备份的持久性的日志服务。它主要用于处理活跃的流式数据。
在大数据系统中,常常会碰到一个问题,整个大数据是由各个子系统组成,数据需要在各个子系统中高性能,低延迟的不停流转。传统的企业消息系统并不是非常适合大规模的数据处理。为了已在同时搞定在线应用(消息)和离线应用(数据文件,日志)Kafka就出现了。Kafka可以起到两个作用:
降低系统组网复杂度。
降低编程复杂度,各个子系统不在是相互协商接口,各个子系统类似插口插在插座上,Kafka承担高速数据总线的作用。
Kafka主要特点:
同时为发布和订阅提供高吞吐量。据了解,Kafka每秒可以生产约25万消息(50 MB),每秒处理55万消息(110 MB)。
可进行持久化操作。将消息持久化到磁盘,因此可用于批量消费,例如ETL,以及实时应用程序。通过将数据持久化到硬盘以及replication防止数据丢失。
分布式系统,易于向外扩展。所有的producer、broker和consumer都会有多个,均为分布式的。无需停机即可扩展机器。
消息被处理的状态是在consumer端维护,而不是由server端维护。当失败时能自动平衡。
支持online和offline的场景。
Kafka的架构:
kafka
Kayka的整体架构非常简单,是显式分布式架构,producer、broker(kafka)和consumer都可以有多个。Producer,consumer实现Kafka注册的接口,数据从producer发送到broker,broker承担一个中间缓存和分发的作用。broker分发注册到系统中的consumer。broker的作用类似于缓存,即活跃的数据和离线处理系统之间的缓存。客户端和服务器端的通信,是基于简单,高性能,且与编程语言无关的TCP协议。几个基本概念:
Topic:特指Kafka处理的消息源(feeds of messages)的不同分类。
Partition:Topic物理上的分组,一个topic可以分为多个partition,每个partition是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)。
Message:消息,是通信的基本单位,每个producer可以向一个topic(主题)发布一些消息。
Producers:消息和数据生产者,向Kafka的一个topic发布消息的过程叫做producers。
Consumers:消息和数据消费者,订阅topics并处理其发布的消息的过程叫做consumers。
Broker:缓存代理,Kafka集群中的一台或多台服务器统称为broker。
消息发送的流程:
message
Producer根据指定的partition方法(round-robin、hash等),将消息发布到指定topic的partition里面
kafka集群接收到Producer发过来的消息后,将其持久化到硬盘,并保留消息指定时长(可配置),而不关注消息是否被消费。
Consumer从kafka集群pull数据,并控制获取消息的offset
Kayka的设计:
1、吞吐量
高吞吐是kafka需要实现的核心目标之一,为此kafka做了以下一些设计:
数据磁盘持久化:消息不在内存中cache,直接写入到磁盘,充分利用磁盘的顺序读写性能
zero-copy:减少IO操作步骤
数据批量发送
数据压缩
Topic划分为多个partition,提高parallelism
2、负载均衡
producer根据用户指定的算法,将消息发送到指定的partition
存在多个partiiton,每个partition有自己的replica,每个replica分布在不同的Broker节点上
多个partition需要选取出lead partition,lead partition负责读写,并由zookeeper负责fail over
通过zookeeper管理broker与consumer的动态加入与离开
3、拉取系统
由于kafka broker会持久化数据,broker没有内存压力,因此,consumer非常适合采取pull的方式消费数据,具有以下几点好处:
简化kafka设计
consumer根据消费能力自主控制消息拉取速度
consumer根据自身情况自主选择消费模式,例如批量,重复消费,从尾端开始消费等
4、可扩展性
当需要增加broker结点时,新增的broker会向zookeeper注册,而producer及consumer会根据注册在zookeeper上的watcher感知这些变化,并及时作出调整。

Kayka的应用场景:
1、消息队列
比起大多数的消息系统来说,Kafka有更好的吞吐量,内置的分区,冗余及容错性,这让Kafka成为了一个很好的大规模消息处理应用的解决方案。消息系统一般吞吐量相对较低,但是需要更小的端到端延时,并尝尝依赖于Kafka提供的强大的持久性保障。在这个领域,Kafka足以媲美传统消息系统,如ActiveMR或RabbitMQ。
2、行为跟踪
Kafka的另一个应用场景是跟踪用户浏览页面、搜索及其他行为,以发布-订阅的模式实时记录到对应的topic里。那么这些结果被订阅者拿到后,就可以做进一步的实时处理,或实时监控,或放到Hadoop/离线数据仓库里处理。
3、元信息监控
作为操作记录的监控模块来使用,即汇集记录一些操作信息,可以理解为运维性质的数据监控吧。
4、日志收集
日志收集方面,其实开源产品有很多,包括Scribe、Apache Flume。很多人使用Kafka代替日志聚合(log aggregation)。日志聚合一般来说是从服务器上收集日志文件,然后放到一个集中的位置(文件服务器或HDFS)进行处理。然而Kafka忽略掉文件的细节,将其更清晰地抽象成一个个日志或事件的消息流。这就让Kafka处理过程延迟更低,更容易支持多数据源和分布式数据处理。比起以日志为中心的系统比如Scribe或者Flume来说,Kafka提供同样高效的性能和因为复制导致的更高的耐用性保证,以及更低的端到端延迟。
5、流处理
这个场景可能比较多,也很好理解。保存收集流数据,以提供之后对接的Storm或其他流式计算框架进行处理。很多用户会将那些从原始topic来的数据进行阶段性处理,汇总,扩充或者以其他的方式转换到新的topic下再继续后面的处理。例如一个文章推荐的处理流程,可能是先从RSS数据源中抓取文章的内容,然后将其丢入一个叫做“文章”的topic中;后续操作可能是需要对这个内容进行清理,比如回复正常数据或者删除重复数据,最后再将内容匹配的结果返还给用户。这就在一个独立的topic之外,产生了一系列的实时数据处理的流程。Strom和Samza是非常著名的实现这种类型数据转换的框架。
6、事件源
事件源是一种应用程序设计的方式,该方式的状态转移被记录为按时间顺序排序的记录序列。Kafka可以存储大量的日志数据,这使得它成为一个对这种方式的应用来说绝佳的后台。比如动态汇总(News feed)。
7、持久性日志(commit log)
Kafka可以为一种外部的持久性日志的分布式系统提供服务。这种日志可以在节点间备份数据,并为故障节点数据回复提供一种重新同步的机制。Kafka中日志压缩功能为这种用法提供了条件。在这种用法中,Kafka类似于Apache BookKeeper项目。

Kayka的设计要点:
1、直接使用linux 文件系统的cache,来高效缓存数据。
2、采用linux Zero-Copy提高发送性能。传统的数据发送需要发送4次上下文切换,采用sendfile系统调用之后,数据直接在内核态交换,系统上下文切换减少为2次。根据测试结果,可以提高60%的数据发送性能。Zero-Copy详细的技术细节可以参考:https://www.ibm.com/developerworks/linux/library/j-zerocopy/
3、数据在磁盘上存取代价为O(1)。kafka以topic来进行消息管理,每个topic包含多个part(ition),每个part对应一个逻辑log,有多个segment组成。每个segment中存储多条消息(见下图),消息id由其逻辑位置决定,即从消息id可直接定位到消息的存储位置,避免id到位置的额外映射。每个part在内存中对应一个index,记录每个segment中的第一条消息偏移。发布者发到某个topic的消息会被均匀的分布到多个part上(随机或根据用户指定的回调函数进行分布),broker收到发布消息往对应part的最后一个segment上添加该消息,当某个segment上的消息条数达到配置值或消息发布时间超过阈值时,segment上的消息会被flush到磁盘,只有flush到磁盘上的消息订阅者才能订阅到,segment达到一定的大小后将不会再往该segment写数据,broker会创建新的segment。
4、显式分布式,即所有的producer、broker和consumer都会有多个,均为分布式的。Producer和broker之间没有负载均衡机制。broker和consumer之间利用zookeeper进行负载均衡。所有broker和consumer都会在zookeeper中进行注册,且zookeeper会保存他们的一些元数据信息。如果某个broker和consumer发生了变化,所有其他的broker和consumer都会得到通知。

猜你喜欢

转载自shenhaiyue.iteye.com/blog/2325823