Kafka

Kafka 是一个实时、容错、可扩展的分布式发布-订阅消息系统,提供发布-订阅解决方案,主要用于处理活跃的流式数据。

关于官网对 Kafka 介绍:

Apache Kafka™ is used for building real-time data pipelines and streaming apps. It is horizontally scalable, fault-tolerant, wicked fast, and runs in production in thousands of companies.

Kafka is a distributed streaming platform. 

Kafka is a distributed, partitioned, replicated commit log service. (分布式、分区、冗余备份、可持久化)

关于 Kafka 的基本介绍参见:Kafka - Introduction

性能特点

  • 为发布-订阅提供高吞吐量(核心目标):生产:25万消息(50 MB)/s,消费:55万消息(110 MB)/s
  • 支持 online在线应用(消息)和 offline离线应用(数据文件,日志)
  • 持久化:存取代价为O(1)的磁盘数据结构、充分利用磁盘的顺序读写性能,性能稳定、防止数据丢失,同时消息持久化到磁盘,支持批量消费
  • 支持 Hadoop 并行数据加载
  • Zero-Copy 技术:减少IO操作步骤,提高发送性能
  • DelayQueue 机制
  • 消息分组压缩:高效信息传输,减少网络带宽消耗
  • 高峰流量缓冲问题

相关术语

  • Broker:Kafka 集群由一个或多个 Kafka 实例组成,该实例称为代理或 Server 或 Broker
  • Topic:每条发布到 Kafka 集群的消息都有一个类别,该类别称为 Topic(话题),Kafka 根据 Topic 对消息归类存储,Topic 是特定类型的消息流,消息是字节的有效负载(Payload),每条消息由一个key,一个value和时间戳构成
  • Partition:并行处理单元,每个 Topic 划分成一个或多个 Partition(提高 Parallelism),每个 Partition 是一个有序、不可变、可持续追加的消息队列,在存储层面是 AppendLog 文件,该文件由多个大小相等的 Segment 组成,每个 Segment 中存储多条消息,消息 ID 由其逻辑位置决定
  • Producer:生产者,发布(推送)消息到 Kafka Broker
  • Consumer:消费者,从 Kafka Broker 读取(拉取)消息的客户端,可以订阅一个或多个 Topic
  • Consumer Group: 每个 Consumer 属于一个特定的 Consumer Group

注意,Broker 没有主从之分,所有 Brokers 是对等的,Brokers 的元数据信息由 ZooKeeper 维护并被所有的 Consumers 共享。

此外,Partition 只是物理上的概念,物理上不同 Topic 的消息分开存储,逻辑上一个 Topic 的消息虽然会保存于一个或多个 Broker 上,但用户只需指定消息的 Topic 即可生产或消费数据而不必关心数据存于何处。任何发布到 Partition 的消息都会被直接追加到 log 文件尾部,每条消息在文件中的位置称为 offset(偏移量 或 消息的ID,long 型数字,有序唯一标识),offset 唯一标记一条消息,偏移量是消费者保存和控制的唯一元数据。但是,Kafka 几乎不允许对消息进行“随机读写”(不可变性)。

基本概念

首先了解下消息队列,维基百科中定义如下:

队列提供了一种异步通信协议,这意味着消息的发送者和接收者不需要同时与消息保持联系,发送者发送的消息会存储在队列中,直到接收者拿到它。

  • Kafka 最重要的基石:消息在文件系统上的缓冲和存储(缓冲用于控制和优化数据流经系统的速度,解决生产消息和消费消息处理速度不一致的情况)
  • Kafka Broker 是无状态的,Consumer 必须自己维护已消费信息的状态
  • 基于时间的消息保留策略(SLA,Service Level Agreement,消息保留时间):当消息在 Broker 中超过一定时间后,自动删除,无论是否被消费
  • Consumers 将状态信息储存在 ZooKeeper 上,Kafka Brokers 通过 ZooKeeper 获取消息状态,Kafka Consumers 通过 ZooKeeper 跟踪消息的 offset

分区目的

  • 并行处理单元,分而治之(Topic分区中的消息只能由消费者组中的一个消费者处理,并按顺序消费)
  • Kafka基于文件存储,不受单台服务器的限制,将消息分散到多个server中,可以处理更多的数据
  • 顺序保证和负载均衡
  • 多partitions,多consumers,提高并发消费的能力

分组目的

消息模型分为两种:队列式和发布-订阅式。

队列:一组消费者从服务器读取消息,一条消息只有其中的一个消费者来处理,多个消费者瓜分处理消息

发布-订阅:消息被广播给所有的消费者,接收到消息的消费者都可以处理此消息

Kafka整合并提供单一统一的消费者抽象模型: 消费者组 (consumer group)。

每个消费者唯一属于一个消费者组, 一个发布在Topic上消息被分发给此消费者组中的一个消费者:

  • 假如所有的消费者都在一个组中,即队列式消息模型
  • 假如所有的消费者都在不同的组中,即发布-订阅式消息模型

实际中,可以创建一些消费者组作为逻辑上的订阅者,每个组包含数目不等的消费者,一个组内的多个消费者用来扩展性能和容错。

核心API

  • Producer API:allows an application to publish a stream of records to one or more Kafka topics.
  • Consumer API:allows an application to subscribe to one or more topics and process the stream of records produced to them.
  • Streams API:allows an application to act as a stream processor, consuming an input stream from one or more input-topics and producing an output stream to one or more output-topics, effectively transforming the input streams to output streams.
  • Connector API:allows building and running reusable producers or consumers that connect Kafka topics to existing applications or data systems.

关于 Zookeeper Kafka

ZooKeeper 是一个高性能快速、高可用、容错、分布式的协调服务,可以构建可靠的、分布式的分层数据结构。

关于官网对 ZooKeeper 介绍:

Apache ZooKeeperTM is an effort to develop and maintain an open-source server which enables highly reliable distributed coordination.

ZooKeeper: A Distributed Coordination Service for Distributed Applications
ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All of these kinds of services are used in some form or another by distributed applications.

对 ZooKeeper 的进一步基本介绍参见:http://zookeeper.apache.org/doc/trunk/zookeeperOver.html

关于数据模型:

  • 分层,使用分布式文件系统目录树作为数据模型
  • 绝对路径访问数据节点,不支持相对路径
  • ZooKeeper data nodes kept data in-memory:每个节点(znode)保存元数据(coordination)信息,eg:status information,location information,configuration,etc. All coordination data are relatively small.
  • The version number, together with the timestamp, allows ZooKeeper to validate the cache and to coordinate updates.

Kafka 是显式分布式架构,其 5 个重要的组件:

Broker, Topic, Producer, Consumer,Zookeeper

其中,ZooKeeper 用于管理和协调 Kafka Broker,Producer 和 Consumer 实现 Kafka 注册的接口,Brokers 承担数据信息中间缓存和分发的作用,客户端和服务器端基于 TCP 协议通信。

消息在 Kafka 系统中的发送流程:

  • Producer 根据指定的 Partition 方法将消息发布到指定 Topic 的 Partition 中(消息如何 Partition 由 Producer 决定)
  • Broker 接收到消息并持久化到硬盘,而不关注消息是否被消费(消息在磁盘的保留时长可配置)
  • Consumer 从 Kafka 集群 pull 数据,并控制获取消息的 offset

信息具体的 push - pull 流程参见:http://www.cnblogs.com/cyfonly/p/5954614.html

注意,每个Consumer只是Consumer Group中的一个进程,一个话题中的某条消息只能被Consumer Group中的一个Consumer进程消费。换言之,如果要求该话题中的某消息能被多个Consumer消费,则这些Consumer必须在不同的Consumer Group中。

关于消息的压缩发送:一组消息在 Producer 端压缩,Broker 端需解压(加大Broker的CPU的负载)

可扩展性

每个 Broker 都通过 ZooKeeper 协调其它 Brokers。当 Kafka 集群中新增 Broker 或者某个 Broker 故障失效时,ZooKeeper 服务将通知生产者和消费者,生产者和消费者会与其它 Broker 协调工作。具体地,当增加 Broker 时,新增的 Broker 会向 ZooKeeper 注册,而 Producer和Consumer 会根据注册在 ZooKeeper 上的 Watcher 感知这些变化,并及时作出调整。

负载均衡

Producer 和 Broker 之间没有负载均衡机制,Broker 和 Consumer 之间利用 ZooKeeper 进行负载均衡(所有 Broker 和 Consumer 都会在 ZooKeeper 中注册)。

  • 每个 Topic 的 Partition 可以有自己的 replication,每个 replication 分布在不同的 Broker 上
  • 若 Topic 的 Partition 存在冗余多份时,选取出一个为 Leader Partition,其余为 Follower Partition:Leader 负责读写操作、Follower 从 Leader 异步地拉取数据来更新本地保持和 Leader 一致(在消息一致性上,Follower 延迟于 Leader)。
  • ZooKeeper 负责 Fail over(故障切换):针对每个 Partition,Kafka 动态维护一组同步副本(ISR),该副本紧跟 Leader 与其内容保持一致,并将最新的 ISR 同步给 ZooKeeper。如果Leader 挂了,一个 Follower(在 ISR 同步副本中)自动成为新的 Leader(Kafka 集群中的每个 Broker 都扮演双重角色,作为一些 Partition 的 Leader,同时也作为其他 Partition 的 Follower)
  • 通过 ZooKeeper 统一协调管理 Broker 与 Consumer 的动态加入与离开(扩展性能)

关于冗余的几个知识点:

  • 规避数据丢失风险,负载均衡、提高Kafka可用性;
  • Producers 和 Consumers 都可感知冗余(利用Watcher);
  • Partition的冗余方式包括:同步冗余和异步冗余;

关于 Kafka 为 某个 Partition 分配 replication 的算法:

  • 将所有 Brokers(假设共 n 个 Brokers)和待分配的 Partition 排序;
  • 将第 i 个 Partition 分配到第(i mod n)个 Broker 上;
  • 将第 i 个 Partition 的第 j 个 replica 分配到第((i + j) mode n)个 Broker 上;

拉取机制

Consumer 采取 pull 的方式消费数据:

  • 简化 Kafka 设计
  • Consumer 根据消费能力自主控制消息拉取速度
  • Consumer 根据自身情况自主选择消费模式(批量消费、重复再消费、从尾端开始消费)

Kafka Stream

基于流处理的客户端程序库(简单、轻量级),用于处理和分析存储在Kafka中的数据,并将处理后的数据写回Kafka或发送到外部系统。

  • 利用Apache Kafka构造分布式流处理程序的Java库
    • 利用Kafka的并发模型实现透明的负载均衡
    • 利用Kafka的分区模型实现水平扩展并保证有序处理
  • Apache Kafka本身作为内部消息层,没有外部系统的依赖
  • one-recored-at-a-time:一次一条记录的处理方式(而不是微批处理)以实现低延迟(毫秒级),同时支持基于事件时间的开窗操作
  • 提供状态存储,支持流处理程序存储和查询数据,同时支持本地状态存储的故障容错和自动恢复
  • 提供两套流处理原语:低层的 Processor API 和高层的 Stream DSL
    • Processor API:允许自定义链接流处理器节点
    • Stream DSL:提供常用的数据变换操作map、filter等

注意,Kafka Stream是Java库、而不是流处理框架。流是Kafka Stream提出的最重要的抽象概念:

  • 它表示一个无限的、不断更新的数据集;
  • 流是一个有序的、可重放(反复的使用)、不可变的、容错的序列;
  • 数据记录的格式是键值对(key-value)
处理器拓扑是流处理代码的逻辑抽象,是由一个或多个流处理器(节点)和流(边)连接而成的流处理图:
  • Source Processor:源处理器,没有上游处理器的特殊类型的流处理器,从一个或多个kafka主题生成输入流,消费消息生成输出流转发到下游流处理器
  • Sink Processor:sink 处理器,没有下游处理器的特殊类型的流处理器,接受上游流处理器的消息输入,输出到一个指定的Kafka主题
流处理方面关于时间的重要概念,Kafka Streams通过TimestampExtractor接口为每个数据记录分配一个时间戳
  • 事件时间:消息生产时间,CreateTime,producer创建消息的时间
  • 摄取时间:消息保存时间,LogAppendTime,leader broker把消息保存到topic分区(写入到log)的时间
  • 处理时间:消息消费时间,consumer消费消息的时间
若要深入了解 Kafka Stream,请参见:Kafka Streams开发者指南
Kafka Stream 实例
利用Kafka Stream实现一个简单的端到端的数据流处理,同样以大数据中的 Hello World - Word Count 为例:
(1)Kafka代码
object WordCountByKafka extends Serializable {
	def main(args: Array[String]): Unit = {
		val sparkConf = new SparkConf().setAppName("WordCountByKafka").setMaster("local[2]")
		val scc = new StreamingContext(sparkConf, Seconds(5))
		
		// kafka配置
		val inputBrokers  = "ip:port_1, ip:port_2, ip:port_3, ..."
		val outputBrokers = "ip:port_1, ip:port_2, ip:port_3, ..."
		val inputTopics = "iTopic_1, iTopic_2, ... ".split(",").toSet
		val outputTopic = "oTopic"
		val kafkaParams = Map[String, String]("metadata.broker.list" -> inputBrokers)
		val kafkaStream = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder]
											(ssc, kafkaParams, inputTopics)
		
		// Word Count
		val lines = kafkaStream.map(_._2)
		val words = lines.flatMap(_.split("\\s+"))
		val counts = words.map((_, 1)).reduceByKey(_+_)
		val countsOrdered = counts.map(x=>(x._2, x._1)).sortByKey(false).map(x=>(x._2, x._1))
															.foreach(println)
		ssc.start()
		ssc.awaitTermination()
	}
}

(2)Producer代码

 
(3)Consumer代码
 
http://blog.csdn.net/u012373815/article/details/53454669
http://blog.csdn.net/ransom0512/article/details/51985983
http://www.tuicool.com/articles/viuIjiq
http://blog.csdn.net/u012373815/article/details/53648757
http://blog.csdn.net/u012373815/article/details/53668135
http://blog.csdn.net/u012373815/article/details/53728101
http://blog.csdn.net/u012373815/article/details/52746910
http://orchome.com/142
 
 
Kafka Stream的编程使用具体参见:

关于环境搭建
(1)Kafka

下载:http://kafka.apache.org/downloads.html

对于 Kafka 工作原理的详细理解,可以下载源码:kafka-0.10.2.1-src.tgz.gz

(2)ZooKeeper

下载:http://zookeeper.apache.org/releases.html#download

对于 ZooKeeper 的源码,参见:...\zookeeper-3.4.6\src\#JavaOr#C

对于 ZooKeeper,入门简介参见:ZooKeeper Getting Started Guide;编程指导参见:ZooKeeper Programming's Guide

运行 Kafka,需要先运行 ZooKeeper,利用 Kafka 自带打包和配置的 ZooKeeper 即可:...\kafka_2.10-0.10.2.1\bin\windows

// 启动 ZooKeeper
zookeeper-server-start.bat zookeeper.properties
// 启动 Kafka
kafka-server-start.bat server.properties
// 创建 Topic-English
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic English
// 查看 Topic
kafka-topics.bat --list --zookeeper localhost:2181
// 生产消息
kafka-console-producer.bat --broker-list localhost:9092 --topic English
// 消费消息
kafka-console-consumer.bat --zookeeper localhost:2181 --topic English --from-beginning
// 停止 Kafka
kafka-server-stop.bat
// 停止 ZooKeeper
zookeeper-server-stop.bat

其中,启动 ZooKeeper,亦可以通过 ...\zookeeper-3.4.6\bin

// 启动 ZooKeeper
zkServer.cmd

至于配置 Brokers 集群,创建 server.properties 的副本:server-1.properties 和 server-2.properties,参数设置如下

.../server-1.properties: 
    broker.id=1 
    listeners=PLAINTEXT://:9093 
    log.dir=/tmp/kafka-logs-1

.../server-2.properties: 
    broker.id=2 
    listeners=PLAINTEXT://:9094 
    log.dir=/tmp/kafka-logs-2

其余具体细节参见:Kafka 安装和启动

参考

posted @ 2017-04-17 16:30 万箭穿心,习惯就好。 阅读(...) 评论(...) 编辑 收藏