共计 6803 个字符,预计需要花费 18 分钟才能阅读完成。
Kafka 是最后由 Linkedin 公司开发,是一个分布式、反对分区的(partition)、多正本的(replica),基于 zookeeper 协调的分布式音讯零碎,它的最大的个性就是能够实时的解决大量数据以满足各种需要场景:比方基于 hadoop 的批处理零碎、低提早的实时零碎、storm/Spark 流式解决引擎,web/nginx 日志、拜访日志,音讯服务等等,用 scala 语言编写,Linkedin 于 2010 年奉献给了 Apache 基金会并成为顶级开源我的项目。**1. 前言 **
音讯队列的性能好坏,其文件存储机制设计是掂量一个音讯队列服务技术水平和最要害指标之一。上面将从 Kafka 文件存储机制和物理构造角度,剖析 Kafka 是如何实现高效文件存储,及理论利用成果。1.1 Kafka 的个性:
- 高吞吐量、低提早:kafka 每秒能够解决几十万条音讯,它的提早最低只有几毫秒,每个 topic 能够分多个 partition, consumer group 对 partition 进行 consume 操作。- 可扩展性:kafka 集群反对热扩大
- 持久性、可靠性:音讯被长久化到本地磁盘,并且反对数据备份避免数据失落
- 容错性:容许集群中节点失败(若正本数量为 n, 则容许 n - 1 个节点失败)- 高并发:反对数千个客户端同时读写
1.2 Kafka 的应用场景:- 日志收集:一个公司能够用 Kafka 能够收集各种服务的 log,通过 kafka 以对立接口服务的形式凋谢给各种 consumer,例如 hadoop、Hbase、Solr 等。- 音讯零碎:解耦和生产者和消费者、缓存音讯等。- 用户流动跟踪:Kafka 常常被用来记录 web 用户或者 app 用户的各种流动,如浏览网页、搜寻、点击等流动,这些流动信息被各个服务器公布到 kafka 的 topic 中,而后订阅者通过订阅这些 topic 来做实时的监控剖析,或者装载到 hadoop、数据仓库中做离线剖析和开掘。- 经营指标:Kafka 也常常用来记录经营监控数据。包含收集各种分布式应用的数据,生产各种操作的集中反馈,比方报警和报告。- 流式解决:比方 spark streaming 和 storm
1.3 Kakfa 的设计思维
- Kakfa Broker Leader 的选举:Kakfa Broker 集群受 Zookeeper 治理。所有的 Kafka Broker 节点一起去 Zookeeper 上注册一个长期节点,因为只有一个 Kafka Broker 会注册胜利,其余的都会失败,所以这个胜利在 Zookeeper 上注册长期节点的这个 Kafka Broker 会成为 Kafka Broker Controller,其余的 Kafka broker 叫 Kafka Broker follower。(这个过程叫 Controller 在 ZooKeeper 注册 Watch)。这个 Controller 会监听其余的 Kafka Broker 的所有信息,如果这个 kafka broker controller 宕机了,在 zookeeper 下面的那个长期节点就会隐没,此时所有的 kafka broker 又会一起去 Zookeeper 上注册一个长期节点,因为只有一个 Kafka Broker 会注册胜利,其余的都会失败,所以这个胜利在 Zookeeper 上注册长期节点的这个 Kafka Broker 会成为 Kafka Broker Controller,其余的 Kafka broker 叫 Kafka Broker follower。例如:一旦有一个 broker 宕机了,这个 kafka broker controller 会读取该宕机 broker 上所有的 partition 在 zookeeper 上的状态,并选取 ISR 列表中的一个 replica 作为 partition leader(如果 ISR 列表中的 replica 全挂,选一个幸存的 replica 作为 leader; 如果该 partition 的所有的 replica 都宕机了,则将新的 leader 设置为 -1,期待复原,期待 ISR 中的任一个 Replica“活”过去,并且选它作为 Leader;或抉择第一个“活”过去的 Replica(不肯定是 ISR 中的)作为 Leader),这个 broker 宕机的事件,kafka controller 也会告诉 zookeeper,zookeeper 就会告诉其余的 kafka broker。- Consumergroup:各个 consumer(consumer 线程)能够组成一个组(Consumer group),partition 中的每个 message 只能被组(Consumer group)中的一个 consumer(consumer 线程)生产,如果一个 message 能够被多个 consumer(consumer 线程)生产的话,那么这些 consumer 必须在不同的组。Kafka 不反对一个 partition 中的 message 由两个或两个以上的同一个 consumer group 下的 consumer thread 来解决,除非再启动一个新的 consumer group。所以如果想同时对一个 topic 做生产的话,启动多个 consumer group 就能够了,然而要留神的是,这里的多个 consumer 的生产都必须是程序读取 partition 外面的 message,新启动的 consumer 默认从 partition 队列最头端最新的中央开始阻塞的读 message。当启动一个 consumer group 去生产一个 topic 的时候,无论 topic 外面有多个少个 partition,无论咱们 consumer group 外面配置了多少个 consumer thread,这个 consumer group 上面的所有 consumer thread 肯定会生产全副的 partition;即使这个 consumer group 下只有一个 consumer thread,那么这个 consumer thread 也会去生产所有的 partition。因而,最优的设计就是,consumer group 下的 consumer thread 的数量等于 partition 数量,这样效率是最高的。同一 partition 的一条 message 只能被同一个 Consumer Group 内的一个 Consumer 生产。不可能一个 consumer group 的多个 consumer 同时生产一个 partition。- Consumer Rebalance 的触发条件:(1): Consumer 减少或删除会触发 Consumer Group 的 Rebalance(2)Broker 的减少或者缩小都会触发 Consumer Rebalance
- Consumer:
Consumer 解决 partition 外面的 message 的时候是 o(1)程序读取的。所以必须保护着上一次读到哪里的 offsite 信息。high level API,offset 存于 Zookeeper 中,low level API 的 offset 由本人保护。一般来说都是应用 high level api 的。Consumer 的 delivery gurarantee,默认是读完 message 先 commmit 再解决 message,autocommit 默认是 true,这时候先 commit 就会更新 offsite+1,一旦解决失败,offsite 曾经 +1,这个时候就会丢 message;也能够配置成读完音讯解决再 commit,这种状况下 consumer 端的响应就会比较慢的,须要等解决完才行。如果 producer 的流量增大,以后的 topic 的 parition 数量 =consumer 数量,这时候的应答形式就是很想扩大:减少 topic 下的 partition,同时减少这个 consumer group 下的 consumer。![image.png](/img/bVcSl2y)
- Delivery Mode:
Kafka producer 发送 message 不必保护 message 的 offsite 信息,因为这个时候,offsite 就相当于一个自增 id,producer 就只管发送 message 就好了。然而 Consumer 端是须要保护这个 partition 以后生产到哪个 message 的 offsite 信息的,这个 offsite 信息,high level api 是保护在 Zookeeper 上,low level api 是本人的程序保护。当应用 high level api 的时候,先拿 message 解决,再定时主动 commit offsite+1(也能够改成手动), 并且 kakfa 解决 message 是没有锁操作的。因而如果解决 message 失败,此时还没有 commit offsite+1,当 consumer thread 重启后会反复生产这个 message。然而作为高吞吐量高并发的实时处理零碎,at least once 的状况下,至多一次会被解决到,是能够容忍的。如果无奈容忍,就得应用 low level api 来本人程序保护这个 offsite 信息,那么想什么时候 commit offsite+ 1 就本人搞定了。- Topic & Partition:Topic 相当于传统音讯零碎 MQ 中的一个队列 queue,producer 端发送的 message 必须指定是发送到哪个 topic,然而不须要指定 topic 下的哪个 partition,因为 kafka 会把收到的 message 进行 load balance,平均的散布在这个 topic 下的不同的 partition 上(hash(message) % [broker 数量])。在物理构造上,每个 partition 对应一个物理的目录(文件夹),文件夹命名是 [topicname]_[partition]_[序号],一个 topic 能够有有数多的 partition,依据业务需要和数据量来设置。在 kafka 配置文件中可随时更高 num.partitions 参数来配置更改 topic 的 partition 数量,在创立 Topic 时通过参数指定 parittion 数量。Topic 创立之后通过 Kafka 提供的工具也能够批改 partiton 数量。一般来说,(1)一个 Topic 的 Partition 数量大于等于 Broker 的数量,能够进步吞吐率。(2)同一个 Partition 的 Replica 尽量扩散到不同的机器,高可用。当 add a new partition 的时候,partition 外面的 message 不会从新进行调配,原来的 partition 外面的 message 数据不会变,新加的这个 partition 刚开始是空的,随后进入这个 topic 的 message 就会从新参加所有 partition 的 load balance。- Partition Replica:每个 partition 能够在其余的 kafka broker 节点上存正本,以便某个 kafka broker 节点宕机不会影响这个 kafka 集群。存 replica 正本的形式是依照 kafka broker 的程序存。例如有 5 个 kafka broker 节点,某个 topic 有 3 个 partition,每个 partition 存 2 个正本,那么 partition1 存 broker1,broker2,partition2 存 broker2,broker3。。。以此类推(replica 正本数目不能大于 kafka broker 节点的数目,否则报错。这里的 replica 数其实就是 partition 的正本总数,其中包含一个 leader,其余的就是 copy 正本)。这样如果某个 broker 宕机,其实整个 kafka 内数据仍然是残缺的。然而,replica 正本数越高,零碎尽管越稳固,然而回来带资源和性能上的降落;replica 正本少的话,也会造成零碎丢数据的危险。(1)怎么传送音讯:producer 先把 message 发送到 partition leader,再由 leader 发送给其余 partition follower。(2)在向 Producer 发送 ACK 前须要保障有多少个 Replica 曾经收到该音讯:依据 ack 配的个数而定。(3)怎么解决某个 Replica 不工作的状况:如果这个部工作的 partition replica 不在 ack 列表中,就是 producer 在发送音讯到 partition leader 上,partition leader 向 partition follower 发送 message 没有响应而已,这个不会影响整个零碎,也不会有什么问题。如果这个不工作的 partition replica 在 ack 列表中的话,producer 发送的 message 的时候会期待这个不工作的 partition replca 写 message 胜利,然而会等到 time out,而后返回失败因为某个 ack 列表中的 partition replica 没有响应,此时 kafka 会主动的把这个部工作的 partition replica 从 ack 列表中移除,当前的 producer 发送 message 的时候就不会有这个 ack 列表下的这个部工作的 partition replica 了。(4)怎么解决 Failed Replica 复原回来的状况:如果这个 partition replica 之前不在 ack 列表中,那么启动后从新受 Zookeeper 治理即可,之后 producer 发送 message 的时候,partition leader 会持续发送 message 到这个 partition follower 上。如果这个 partition replica 之前在 ack 列表中,此时重启后,须要把这个 partition replica 再手动加到 ack 列表中。(ack 列表是手动增加的,呈现某个部工作的 partition replica 的时候主动从 ack 列表中移除的)- Partition leader 与 follower:partition 也有 leader 和 follower 之分。leader 是主 partition,producer 写 kafka 的时候先写 partition leader,再由 partition leader push 给其余的 partition follower。partition leader 与 follower 的信息受 Zookeeper 管制,一旦 partition leader 所在的 broker 节点宕机,zookeeper 会冲其余的 broker 的 partition follower 上抉择 follower 变为 parition leader。- Topic 调配 partition 和 partition replica 的算法:(1)将 Broker(size=n)和待调配的 Partition 排序。(2)将第 i 个 Partition 调配到第(i%n)个 Broker 上。(3)将第 i 个 Partition 的第 j 个 Replica 调配到第((i + j) % n)个 Broker 上
- Partition ack:当 ack=1,示意 producer 写 partition leader 胜利后,broker 就返回胜利,无论其余的 partition follower 是否写胜利。当 ack=2,示意 producer 写 partition leader 和其余一个 follower 胜利的时候,broker 就返回胜利,无论其余的 partition follower 是否写胜利。当 ack=-1[parition 的数量] 的时候,示意只有 producer 全副写胜利的时候,才算胜利,kafka broker 才返回胜利信息。这里须要留神的是,如果 ack= 1 的时候,一旦有个 broker 宕机导致 partition 的 follower 和 leader 切换,会导致丢数据。![image.png](/img/bVcSl4b)
- message 状态:在 Kafka 中,音讯的状态被保留在 consumer 中,broker 不会关怀哪个音讯被生产了被谁生产了,只记录一个 offset 值(指向 partition 中下一个要被生产的音讯地位),这就意味着如果 consumer 解决不好的话,broker 上的一个音讯可能会被生产屡次。- message 长久化:Kafka 中会把音讯长久化到本地文件系统中,并且放弃 o(1) 极高的效率。咱们家喻户晓 IO 读取是十分耗资源的性能也是最慢的,这就是为了数据库的瓶颈常常在 IO 上,须要换 SSD 硬盘的起因。然而 Kafka 作为吞吐量极高的 MQ,却能够十分高效的 message 长久化到文件。这是因为 Kafka 是程序写入 o(1)的工夫复杂度,速度十分快。也是高吞吐量的起因。因为 message 的写入长久化是程序写入的,因而 message 在被生产的时候也是按程序被生产的,保障 partition 的 message 是程序生产的。个别的机器, 单机每秒 100k 条数据。https://www.cnblogs.com/cxxjohnson/p/8921661.html
正文完