0、资源
官方文档:kafka.apachecn.org/documentati…
趣味文章:zhuanlan.zhihu.com/p/68052232
w3c: www.w3cschool.cn/apache_kafk…
未用到:
并发编程网:ifeve.com/kafka-1/
producer、consumer、topic、broker。
从技术角度,topic标签实际就是队列,生产者把所有消息都放到对应的队列里了,消费者到指定的队列里取。
1、基础
1.1、引入
对于大数据,我们要考虑的问题有很多,首先海量数据如何收集(如 Flume);然后对于收集到的数据如何存储(典型的分布式文件系统 HDFS、分布式数据库 HBase、NoSQL 数据库 Redis);其次存储的数据不是存起来就没事了,要通过计算从中获取有用的信息,这就涉及到计算模型(典型的离线计算 MapReduce、流式实时计算Storm、Spark),或者要从数据中挖掘信息,还需要相应的机器学习算法。在这些之上,还有一些各种各样的查询分析数据的工具(如 Hive、Pig 等)。除此之外,要构建分布式应用还需要一些工具,比如分布式协调服务 Zookeeper 等等。
Kafka 是一种分布式高吞吐量的消息系统,具有高性能、持久化、多副本备份、横向扩展能力。一般在架构设计中起到解耦、削峰、异步处理的作用。
- 什么是消息系统?
消息系统负责将数据从一个应用程序传输到另外一个应用程序,使得应用程序可以专注于处理逻辑,而不用过多的考虑如何将消息共享出去。
-
消息系统有两种消息传递模式——
-
点对点的消息系统
消息被保留在队列中;
生产者将消息放入消息队列后,由消费者主动的去拉取消息进行消费;
多个消费者可以同时消耗队列中的消息,但每个消息只能被一个消费者处理(如订单处理系统);
一旦有一个消费者将其消费掉,消息就从该队列中消失。
-
发布-订阅消息系统
消息被保留在主题中;
生产者将消息放入消息队列后,队列会将消息推送给订阅过该类消息的消费者。
-
1.2、基础概念与简介
-
broker:
Kafka 集群中有很多台 Server,将每一台 Server 称为一个 kafka 实例,也叫做 broker。
-
topic(主题) :
一个 topic 里保存的是同一类消息,相当于对消息的分类。
-
partition(分区) :
每个 topic 都可以分成多个 partition,每个 partition 在存储层面是 append log 文件。任何发布到此 partition 的消息都会被直接追加到 log 文件的尾部。
-
为什么要进行分区呢?
- 方便扩展。因为一个topic可以有多个partition,所以我们可以通过扩展机器去轻松的应对日益增长的数据量。
- 提高并发。以partition为读写单位,可以多个消费者同时消费数据,提高了消息的处理效率。
-
kafka特点:
- kafka 是一个基于发布-订阅的分布式消息系统(消息队列)
- kafak 的消息数据保存在磁盘,每个 partition 对应磁盘上的一个文件,消息写入就是简单的文件追加,文件可以在集群内复制备份以防丢失
- 即使消息被消费,kafka 也不会立即删除该消息,可以通过配置使得过一段时间后自动删除以释放磁盘空间
- kafka依赖分布式协调服务Zookeeper,适合离线/在线信息的消费,与 storm 和 spark 等实时流式数据分析常常结合使用
1.3、基本工作原理
数据生产过程
producer采用push模式将数据发布到broker,每条消息追加到分区中,顺序写入磁盘,所以保证同一分区内的数据是有序的!
对于生产者要写入的一条记录,可以指定四个 参数 :分别是 topic、partition、key 和 value,其中 topic 和 value(要写入的数据)是必须要指定的,而 key 和 partition 是可选的。 对于一条记录,先对其进行序列化,然后按照 Topic 和 Partition,放进对应的发送队列中。如果 Partition 没填 ,那么情况会是这样的:
a、Key 填了。按照 Key 进行哈希,相同 Key 去一个 Partition。
b、Key 没填。Round-Robin 来选 Partition。
producer 将会和Topic下所有 partition leader 保持 socket 连接,消息由 producer 直接通过 socket 发送到 broker。 ——其中 partition leader 的位置( host : port )注册在 zookeeper 中,producer 作为 zookeeper client,已经注册了 watch 用来监听 partition leader 的变更事件,因此,可以准确的知道谁是当前的 leader。
producer 端采用异步发送:将多条消息暂存在 buffer ,并将他们批量的发送到 broker,小数据 IO 太多,会拖慢整体的网络延迟,批量延迟发送事实上提升了网络效率。
数据消费过程
订阅 Topic 是以一个Group来订阅的,发送到 Topic 的消息,只会被订阅此 Topic 的每个 Group中的一个 consumer 消费。
一个 Partition,只能被同一个Group里的一个消费者消费,但是可以同时被多个Group消费;同一个Group的消费者可以消费同一topic下不同分区的数据。
在每一个消费者中唯一保存的元数据是offset(偏移量)即消费在log中的位置,偏移量由消费者所控制。
副本(replicated )
kafka 还可以配置partitions需要备份的个数(replicas),每个 partition 将会被备份到多台机器上,以提高可用性,备份的数量可以通过配置文件指定。
这种冗余备份的方式在分布式系统中是很常见的,那么既然有副本,就涉及到对同一个文件的多个备份如何进行管理和调度。kafka 采取的方案是:每个 partition 选举一个 server 作为“leader”,由 leader 负责所有对该分区的读写,其他 server 作为 follower 只需要简单的与 leader 同步,保持跟进即可。如果原来的 leader 失效,会重新选举由其他的 follower 来成为新的 leader。
至于如何选取 leader,实际上如果我们了解 ZooKeeper,就会发现其实这正是 Zookeeper 所擅长的,Kafka 使用 ZK 在 Broker 中选出一个 Controller,用于 Partition 分配和 Leader 选举。
另外,这里我们可以看到,实际上作为 leader 的 server 承担了该分区所有的读写请求,因此其压力是比较大的,从整体考虑,有多少个 partition 就意味着会有多少个leader,kafka 会将 leader 分散到不同的 broker 上,确保整体的负载均衡。
push vs pull
Kafka 采取的方式: producer 把数据 push 到 broker,然后 consumer 从 broker 中 pull 数据。我们称之为pull-based系统。
- push-based缺点:
同样存在push-based系统。然而,由于 broker 控制着数据传输速率, 所以 push-based 系统很难处理不同的 consumer。让 broker 控制数据传输速率主要是为了让 consumer 能够以可能的最大速率消费;不幸的是,这导致着在 push-based 的系统中,当消费速率低于生产速率时,consumer 往往会不堪重负(本质上类似于拒绝服务攻击)。
- pull-based优点:
- 当 consumer 速率落后于 producer 时,可以在适当的时间赶上来。还可以通过使用某种 backoff 协议来减少这种现象:即 consumer 可以通过 backoff 表示它已经不堪重负了,然而通过获得负载情况来充分使用 consumer(但永远不超载)这一方式实现起来比它看起来更棘手。前面以这种方式构建系统的尝试,引导着 Kafka 走向了更传统的 pull 模型。
- 它可以大批量生产要发送给 consumer 的数据。而 push-based 系统必须选择立即发送请求或者积累更多的数据,然后在不知道下游的 consumer 能否立即处理它的情况下发送这些数据。如果系统调整为低延迟状态,这就会导致一次只发送一条消息,以至于传输的数据不再被缓冲,这种方式是极度浪费的。 而 pull-based 的设计修复了该问题,因为 consumer 总是将所有可用的(或者达到配置的最大长度)消息 pull 到 log 当前位置的后面,从而使得数据能够得到最佳的处理而不会引入不必要的延迟。
\