一 集群
1 注册
kafka使用zookeeper来维护集群,在broker启动的时候,它会创建一个临时节点把自己的id注册到zookeeper。Kafka集群会订阅这个信息,当有broker加入货退出集群时,Kafka集群会获得通知。
2 集群中控制器的选举
Kafka集群中的broker会在启动的时候会在zookeeper中创建一个临时节点/controller来让自己成为控制器(主节点)。但是只有一个节点会创建成功,而其他节点会收到该节点已存在的信息,并订阅这个通知。当这个控制器被关闭或者断开连接之后,zookeeper上的这个临时节点会消息,同时其他节点会收到这个通知,然后这些broker就会尝试让自己注册成为主节点,但依然只有其中一个会注册成功。
在某个broker成为新的控制器之后,会发出了epoch的消息通知,这个epoch是根据zookeeper的条件递增的值,其他broker在收到epoch之后,则以最新最大的epoch值为准,防止脑裂。
小结:kafka使用zookeeper的临时节点来选举控制器,并在节点加入或退出集群时通知其他控制器。通过epoch来避免脑裂。
二 物理存储
kafka的配置文件中,可以配置log.dirs,用于存储数据分区的路径。注意它不是日志。日志配置是log4.properties文件。
1 文件
- 管理
分区会被分成多个片段,默认情况下每个片段包含1GB或者7天的数据(满足其中一个条件就切分),当broker往分区写数据时,如果达到分段的上限,就关闭当前文件,并打开一个新文件。
当前正在写入的数据片段(活跃片段)是不会被删除的。比如配置了保留天数为1天,但是该片段写的数据比较少,片段中包含了3天前的数据,那么这些数据是不会被删除的,因为当前片段正在被使用中。 - 格式
kafka的消息和偏移量都保存在文件里,同时生产者和消费者的数据格式是一样的。
除了键、值、偏移量、消息大小、消息格式、校验数据、版本号、压缩算法和时间戳。
如果生产者没有发送时间戳,则该时间戳为消息到达broker的时间。
2 索引
消费者可以从kafka的任意可用偏移量位置开始读取消息。
Kafka为每个分区维护了一个索引,索引把偏移量映射到片段文件和偏移量所在文件里位置信息。这样可以更快的定位到指定的偏移量。
索引也被分成片段,在删除消息数据片段的时候,可以删除相应的索引。
三 数据的可靠性
1 ACID
ACID指的是原子性、一致性、隔离性和持久性。
kafka可以保证分区消息的顺序。
只要还有一个副本是正常运行的,那么已经提交的消息就不会丢失。
消费者只会读取到已经提交的消息。
2 发送确认
生产者可以选择3种不同的确认模式。
acks=0
生产者通过网络把消息发送出去就认为消息已经成功写入到kafka了。(可能会丢失消息)
acks=1
控制节点在收到消息并把它写入到分区文件时会返回成功确认。(如果此时控制节点刚好故障,消息还没有来得及被复制到其他节点,则数据会丢失)
acks=all
控制节点会等到所有同步副本都收到消息后,才返回成功确认。可以使用min.insync.replicas参数来配置最少要等待多少个节点返回成功。此时如果生产者一直重试直到收到消息被成功提交,则可以最大程度的保证数据不被丢失。
3 错误处理
- 生产者重试次数
生产者向broker发送消息后会收到成功或者错误的响应。
如果是重试之后可以解决的,则可以使用重试机制来重新发送消息。
但是,重新发送一个已经失败的消息会带来一些风险,可能会写入重复数据。 - 其他错误
对于重试无法解决的错误响应,需要在代码中解决。
比如说:消息大小错误、认证错误、序列化错误、生产者达到重试次数上限时或消息占用内存达到上限时发送的错误。
四 数据管道
连接器可以构建仅一次传递的端到端的数据管道。