第三章目录
第三章 KafKa
Kafka是一个分布式、高吞吐的消息发布与订阅系统
3.1 Kafka 原理
3.1.1 数据一致性
3.1.1.1 producer端:ACK机制
0:不等待节点同步成功就发送下一条消息,消息发送失败就会直接丢失
1:等待leader副本同步成功才发送下一条消息,如果leader在备份数据到follow前宕机就会丢失数据
-1 : 等待kafka认为follow同步成功才发送下一条消息,不可能丢失数据。
3.1.1.2 kafka端:LEO-HW机制
- 当数据写入leader副本后,会立刻更新分区的最新偏移量LogEndOffset
- 直到指定数量的follow副本同步成功后才会更新偏移量HighWatermark(最少同步数量可以在参数中设置)
- 消费者只能读取到HW的位置,不能读到LEO的位置
- 发生重新选举后,所有broker都会将数据截断到HW的位置,宕机恢复的leader也会截断到HW的位置。
截断机制保证了kafka内部数据的一致性,但这也是ack=1有可能导致数据丢失的原因。
--以上所有偏移量均存储在zk中。
3.1.1.3 consumer端:使用"恰好一次"的一致性策略
- direct消费数据并手动维护偏移量的存储
- 确保数据消费完成后才更新偏移量(使用事务)
3.1.2 存储机制
3.1.2.1 分区存储
kafka通过topic来分主题存放数据,主题内有分区,分区有多个segment,每个segment存储多条消息,消息id由位置决定,可以直接通过消息id定位到消息存储的位置。
3.1.2.2 顺序写入
生产者发送的消息默认会被均匀分布到多个partition上,broker将消息往对应partition的最后一个segment上添加该消息,定时刷写到磁盘。segment达到阀值时会创建新的segement。
3.1.2.3 可靠性
kafka为每个分区都维护了N个副本repli,确保kafka数据的可靠性,并通过LEO-HW机制确保了数据的一致性。
3.2 其他
3.2.1 kafka扩容
将服务器添加到Kafka集群非常简单,只需为其分配唯一的 broker ID并在您的新服务器上启动Kafka即可。但是,这些新的服务器不会自动分配到任何数据分区,除非将分区移动到这些分区,否则直到创建新 topic 时才会提供服务。所以通常当您将机器添加到群集中时,您会希望将一些现有数据迁移到这些机器上。迁移数据的过程是手动启动的,但是完全自动化。在迁移数据时,Kafka会将新服务器添加为正在迁移的分区的 follower,并允许它完全复制该分区中的现有数据。当新服务器完全复制了此分区的内容并加入了同步副本时,其中一个现有副本将删除其分区的数据。分区重新分配工具可用于跨 broker 移动分区。理想的分区分布将确保所有 broker 的数据负载和分区大小比较均衡。分区重新分配工具不具备自动分析Kafka集群中的数据分布并移动分区以获得均匀负载的功能。因此,管理员必须找出哪些 topic 或分区应该移动。
分区重新分配工具可以以3种互斥方式运行:
--generate: 在此模式下,给定一个 topic 列表和一个 broker 列表,该工具会生成一个候选重新分配,以将指定的 topic 的所有分区移动到新的broker。此选项仅提供了一种便捷的方式,可以根据 tpoc 和目标 broker 列表生成分区重新分配计划。
--execute: 在此模式下,该工具基于用户提供的重新分配计划启动分区重新分配。(使用--reassignment-json-file选项)。这可以是由管理员制作的自定义重新分配计划,也可以是使用--generate选项提供的自定义重新分配计划。
--verify: 在此模式下,该工具将验证最近用 --execute 模式执行间的所有分区的重新分配状态。状态可以是成功完成,失败或正在进行
自动将数据迁移到新机器分区重新分配工具可用于将当前一组 broker 的一些 topic 移至新增的topic。这在扩展现有群集时通常很有用,因为将整个 topic 移动到新 broker 集比移动一个分区更容易。当这样做的时候,用户应该提供需要移动到新的 broker 集合的 topic 列表和新的目标broker列表。该工具然后会均匀分配新 broker 集中 topic 的所有分区。在此过程中,topic 的复制因子保持不变。实际上,所有输入 topic 的所有分区副本都将从旧的broker 组转移到新 broker中。例如,以下示例将把名叫foo1,foo2的 topic 的所有分区移动到新的 broker 集5,6。最后,foo1和foo2的所有分区将只在<5,6> broker 上存在。由于该工具接受由 topic 组成的输入列表作为json文件,因此首先需要确定要移动的 topic 并创建 json 文件,如下所示:
> cat topics-to-move.json
{"topics": [{"topic": "foo1"},
{"topic": "foo2"}],
"version":1
}
一旦json文件准备就绪,就可以使用分区重新分配工具来生成候选分配:
> bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --topics-to-move-json-file topics-to-move.json --broker-list "5,6" --generate
//当前分区副本分配
{"version":1,
"partitions":[{"topic":"foo1","partition":2,"replicas":[1,2]},
{"topic":"foo1","partition":0,"replicas":[3,4]},
{"topic":"foo2","partition":2,"replicas":[1,2]},
{"topic":"foo2","partition":0,"replicas":[3,4]},
{"topic":"foo1","partition":1,"replicas":[2,3]},
{"topic":"foo2","partition":1,"replicas":[2,3]}]
}
//建议的分区重新分配配置
{"version":1,
"partitions":[{"topic":"foo1","partition":2,"replicas":[5,6]},
{"topic":"foo1","partition":0,"replicas":[5,6]},
{"topic":"foo2","partition":2,"replicas":[5,6]},
{"topic":"foo2","partition":0,"replicas":[5,6]},
{"topic":"foo1","partition":1,"replicas":[5,6]},
{"topic":"foo2","partition":1,"replicas":[5,6]}]
}
</