kafka(一)—基本概念

本文已同步至我的博客 liaosi'blog-kafka(一)—基本概念

Kafka简介

Kafka是用scala语言编写,最初由Linkedin公司开发,后贡献给了Apache基金会并成为顶级开源项目。是一个分布式、支持分区的(partition)、多副本的(replication),基于zookeeper协调的分布式消息系统,它的最大的特性就是能够实时的处理大量数据以知足各类需求场景:好比基于hadoop的批处理系统、低延迟的实时系统、storm/Spark流式处理引擎,web/nginx日志、访问日志,消息服务等等。mysql

Kafka是一个类JMS消息队列,结合了JMS中的两种模式,能够有多个消费者主动拉取数据。虽然它提供了相似于JMS的特性,可是在设计实现上彻底不一样,此外它并非JMS规范的实现,在JMS中只有点对点模式才有消费者主动拉取数据。nginx

1.Kafka的特性

  • 高吞吐量、低延迟:kafka每秒能够处理几十万条消息,它的延迟最低只有几毫秒,每一个topic能够分多个partition,consumer group 对 partition 进行consume操做。
  • 可扩展性:kafka集群支持热扩展
  • 持久性、可靠性:消息被持久化到本地磁盘,而且支持数据备份防止数据丢失
  • 容错性:容许集群中节点失败(若副本数量为n,则容许n-1个节点失败)
  • 高并发:支持数千个客户端同时读写
  • 顺序性:由生产者发送到一个特定的主题分区的消息将被以他们被发送的顺序来追加。也就是说,
    若是一个消息M1和消息M2都来自同一个生产者,M1先发,那么M1将有一个低于M2的偏移,会更早在日志中出现。
    消费者看到的记录排序就是记录被存储在日志中的顺序。

2.Kafka的使用场景:

  • 日志收集:一个公司能够用Kafka能够收集各类服务的log,经过kafka以统一接口服务的方式开放给各类consumer,例如Hadoop、Hbase、Solr等。
  • 消息系统:解耦生产者和消费者、缓存消息等。
  • 用户活动跟踪:Kafka常常被用来记录web用户或者app用户的各类活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,而后订阅者经过订阅这些topic来作实时的监控分析,或者装载到hadoop、数据仓库中作离线分析和挖掘。
  • 运营指标:Kafka也常常用来记录运营监控数据。包括收集各类分布式应用的数据,生产各类操做的集中反馈,好比报警和报告。
  • 流式处理:好比 Spark Streaming 和 Storm。
  • 事件源

Kafka的几个重要概念

官方文档:Kafka官网文档
Kafka的运行架构以下图,各组件之间经过TCP协议通讯:web

1.Broker

kafka 集群由多个 kafka 实例组成,每一个实例 (server) 称为 broker ,在集群中每一个broker都有一个惟一brokerid,不得重复。 不管是 kafka 集群,仍是 producer 和 consumer 都依赖于 zookeeper 来保证系统可用性,为集群保存一些 meta (元数据)信息。算法

2.Topics And Logs

主题(topic)是一种分类或发布的一系列记录的名义上的名字。Kafka的主题始终是支持多用户订阅的;也就是说,一个主题能够有零个,一个或多个消费者订阅写入的数据。
对于每个主题,Kafka集群保持一个分区日志文件,看下图:sql

每一个分区都由一系列有序的、不可变的消息组成,这些消息被连续的追加到分区中。分区中的每一个消息都有一个连续的序列号叫作offset,用来在分区中惟一的标识这个消息。apache

在一个可配置的时间段内,Kafka集群保留全部发布的消息,无论这些消息有没有被消费。好比,若是消息的保存策略被设置为2天,那么在一个消息被发布的两天时间内,它都是能够被消费的,以后它将被丢弃以释放空间。Kafka的性能是和数据量无关的常量级的,因此保留太多的数据并非问题。缓存

实际上每一个consumer惟一须要维护的数据是消息在日志中的位置,也就是offset。这个offset有consumer来维护:通常状况下随着consumer不断的读取消息,这offset的值不断线性增长,但其实consumer能够在任何它想要的位置读取记录,好比它能够将offset设置成为一个旧的值来重读以前的消息。服务器

正由于以上的特色,使Kafka consumers很是的轻量级:它们能够在不对集群和其余consumer形成影响的状况下读取消息。例如,你可使用命令行工具去"tail"任何主题的内容,而不会对其余正在消费该消息的consumer形成影响。session

4.Producers

Producer将消息发布到它指定的topic中,并负责决定发布到哪一个分区。一般简单的由负载均衡机制随机选择分区,也能够根据一些更复杂的语义分区算法(好比基于记录一些键值)来完成。使用的更多的是第二种。默认是defaultPartition Utils.abs(key.hashCode) % numPartitions架构

5.Consumers

每一个 Consumer 进程都会划归到一个逻辑的Consumer Group中,逻辑的订阅者是Consumer Group,同一个 Consumer Group 中的 Consumer 能够在不一样的程序中,也能够在不一样的机器上。因此一条message能够被多个订阅该 message 所在的topic的每个Consumer Group 所消费,也就好像是这条message被广播到每一个Consumer Group同样。而每一个Consumer Group中,相似于一个Queue(JMS中的Queue)的概念差很少,即topic中的一条message只会被Consumer Group中的一个Consumer消费。

上图显示,一个kafka cluster中的某个topic有4个分区(P0-P3)和2个consumer组。A组有2个consumer,B组有4个consumer。

其实上面所说的订阅关系还不够明确,其实topic中的partition被分配到某个consumer上,也就是某个consumer订阅了某个partition。Consumer Group 订阅的是topic,可是consumer订阅的是partition,而不是message。因此在同一时间点上,订阅到同一个partition的consumer必然属于不一样的Consumer Group。另外,partition分配的工做是在consumer leader中完成的。

Consumer 与 Consumer Group 的动态维护

当一个Consumer 进程挂掉 或者是卡住时,该Consumer所订阅的partition会被从新分配到该group内的其它的Consumer上。当一个consumer加入到一个Consumer Group中时,一样会从其它的Consumer中分配出一个或者多个partition 到这个新加入的Consumer。

当启动一个Consumer时,会指定它要加入的group,使用的是配置项:group.id。

为了维持Consumer 与 Consumer Group的关系,须要Consumer周期性的发送heartbeat到coordinator(协调者,在早期版本,以zookeeper做为协调者。后期版本则以某个broker做为协调者)。当Consumer因为某种缘由不能发Heartbeat到coordinator时,而且时间超过session.timeout.ms时,就会认为该consumer已退出,它所订阅的partition会分配到同一group 内的其它的consumer上。而这个过程,被称为rebalance。

若是一个consumer 进程一直在周期性的发送heartbeat,可是它就是不消费消息,这种状态称为livelock状态。

Coordinator

Coordinator 协调者,协调consumer、broker。早期版本中Coordinator,使用zookeeper实现,可是这样作,rebalance的负担过重。为了解决scalable的问题,再也不使用zookeeper,而是让每一个broker来负责一些group的管理,这样consumer就彻底再也不依赖zookeeper了。

Consumer链接到coordinator

从Consumer的实现来看,在执行poll或者是join group以前,都要保证已链接到Coordinator。链接到coordinator的过程是:

1)链接到最后一次链接的broker(若是是刚启动的consumer,则要根据配置中的borker)。它会响应一个包含coordinator信息(host, port等)的response。

2)链接到coordinator。

Consumer Group Management

Consumer Group 管理中,也是须要coordinator的参与。一个Consumer要join到一个group中,或者一个consumer退出时,都要进行rebalance。进行rebalance的流程是:

1)会给一个coordinator发起Join请求(请求中要包括本身的一些元数据,例如本身感兴趣的topics)

2)Coordinator 根据这些consumer的join请求,选择出一个leader,并通知给各个consumer。这里的leader是consumer group 内的leader,是由某个consumer担任,不要与partition的leader混淆。

3)Consumer leader 根据这些consumer的metadata,从新为每一个consumer member从新分配partition。分配完毕经过coordinator把最新分配状况同步给每一个consumer。

4)Consumer拿到最新的分配后,继续工做。

Kafka如何保证消息的有序性

传统的队列在服务器上保存有序的消息,若是多个consumers同时从这个服务器消费消息,服务器就会以消息存储的顺序向consumer分发消息。虽然服务器按顺序发布消息,可是消息是被异步的分发到各consumer上,因此当消息到达时可能已经失去了原来的顺序,这意味着并发消费将致使顺序错乱。为了不故障,这样的消息系统一般使用“专用consumer”的概念,其实就是只容许一个消费者消费消息,固然这就意味着失去了并发性。

在这方面Kafka作的更好,经过分区的概念,Kafka能够在多个consumer组并发的状况下提供较好的有序性和负载均衡。将每一个分区分只分发给一个consumer组,这样一个分区就只被这个组的一个consumer消费,就能够顺序的消费这个分区的消息。由于有多个分区,依然能够在多个consumer组之间进行负载均衡。注意consumer组的数量不能多于分区的数量,也就是有多少分区就容许多少并发消费。

Kafka只能保证一个分区以内消息的有序性,在不一样的分区之间是不能够的,这已经能够知足大部分应用的需求。若是须要topic中全部消息的有序性,那就只能让这个topic只有一个分区,固然也就只有一个consumer组消费它。

6.Distribution

Producer将消息发布到它指定的topic中,并负责决定发布到哪一个分区。一般简单的由负载均衡机制随机选择分区,但也能够经过特定的分区函数选择分区。使用的更多的是第二种。默认是defaultPartition Utils.abs(key.hashCode) % numPartitions
每一个分区(partition)在 Kafka 集群的若干服务中都有副本,这样这些持有副本的服务能够共同处理数据和请求,副本数量是能够配置的(replication-factor 1),副本使Kafka具有了容错能力。
每个分区都由一个服务器做为“leader”,零或若干服务器做为“followers”,leader负责处理消息的读和写,与此同时,follower会被动的去复制leader上的数据。
若是leader发生故障,followers中的一台则会自动成为leader。每台服务器能够做为一些分区的leader,同时也能够做为其余分区的follower,这样集群就会据有较好的负载均衡。特别强调,和mysql中主从有区别,mysql作主从是为了读写分离,在kafka中读写操做都是leader。

在Kafka partition中,每一个消息有一个惟一标识,即partition内的offset。每一个consumer group中的订阅到某个partition的consumer在从partition中读取数据时,是依次读取的。

上图中,Consumer A、B分属于不用的Consumer Group。Consumer B读取到offset =11,Consumer A读取到offset=9 。这个值表示Consumer Group中的某个Consumer 在下次读取该partition时会从哪一个offset的 message开始读取,即 Consumer Group A 中的Consumer下次会从offset = 9 的message 读取, Consumer Group B 中的Consumer下次会从offset = 11 的message 读取。

这里并无说是Consumer A 下次会从offset = 9 的message读取,缘由是Consumer A可能会退出Group ,而后Group A 进行rebalance,即从新分配分区。

Kafka的特色

1.Kafka做为消息系统

如何将Kafka的流的概念和传统的企业信息系统做比较?

消息处理模型从来有两种:队列和发布-订阅。在队列模型中,一组消费者能够从服务器读取记录,每一个记录都会被其中一个消费者处理; 在发布-订阅模式里,记录被广播到全部的消费者。这两种模式都具备必定的优势和弱点。队列的优势是它可让你把数据分配到多个消费者去处理,它可让您扩展你的处理能力。不幸的是,队列不支持多个订阅者,一旦一个进程读取了数据,这个数据就会消失。发布-订阅模式可让你广播数据到多个进程,可是由于每个消息发送到每一个订阅者,没办法对订阅者处理能力进行扩展。

Kafka的消费群的推广了这两个概念。消费群能够像队列同样让消息被一组进程处理(消费群的成员),与发布 – 订阅模式同样,Kafka可让你发送广播消息到多个消费群。

Kafka的模型的优势是,每一个主题都具备这两个属性,它能够扩展处理能力,也能够实现多个订阅者,没有必要二选一。

Kafka比传统的消息系统具备更强的消息顺序保证的能力。

传统的消息队列的消息在队列中是有序的,多个消费者从队列中消费消息,服务器按照存储的顺序派发消息。然而,尽管服务器是按照顺序派发消息,可是这些消息记录被异步传递给消费者,消费者接收到的消息也许已是乱序的了。这实际上意味着消息的排序在并行消费中都将丢失。消息系统一般靠 “排他性消费”( exclusive consumer)来解决这个问题,只容许一个进程从队列中消费,固然,这意味着没有并行处理的能力。

Kafka作的更好。经过一个概念:并行性-分区-主题实现主题内的并行处理,Kafka是可以经过一组消费者的进程同时提供排序保证和负载均衡。每一个主题的分区指定给每一个消费群中的一个消费者,使每一个分区只由该组中的一个消费者所消费。经过这样作,咱们确保消费者是一个分区惟一的读者,从而顺序的消费数据。由于有许多的分区,因此负载还可以均衡的分配到不少的消费者实例上去。可是请注意,一个消费群的消费者实例不能比分区数量多。

2.Kafka做为存储系统

任何消息队列都可以解耦消息的生产和消费,还可以有效地存储正在传送的消息。Kafka不同凡响的是,它是一个很是好的存储系统。

Kafka把消息数据写到磁盘和备份分区。Kafka容许生产者等待返回确认,直到副本复制和持久化所有完成才认为成功,不然则认为写入服务器失败。

Kafka使用的磁盘结构很好扩展,Kafka将执行相同的策略无论你是有50 KB或50TB的持久化数据。

因为存储的重要性,并容许客户控制本身的读取位置,你能够把Kafka认为是一种特殊用途的分布式文件系统,致力于高性能,低延迟的有保障的日志存储,可以备份和自我复制。

相关文章
相关标签/搜索