文章目录

  • ZooKeeper 基本概念
  • ZooKeeper 主要提供下面几个功能:
  • 关于 ZooKeeper 的一些重要概念:
  • ZooKeeper 特点
  • kafka简介
  • 基本术语
  • topic中partition存储分布
  • 基本交互原理
  • Kakfa Broker Leader的选举


ZooKeeper 基本概念

ZooKeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心。

服务生产者将自己提供的服务注册到 ZooKeeper 中心,服务的消费者在进行服务调用的时候先到 ZooKeeper 中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据。

kafka无zookeeper部署 kafka 不依赖zookeeper_zookeeper

ZooKeeper 主要提供下面几个功能:

  • 集群管理:容错、负载均衡。
  • 配置文件的集中管理。
  • 集群的入口。
    重要概念总结

关于 ZooKeeper 的一些重要概念:

  • ZooKeeper 本身就是一个分布式程序(只要半数以上节点存活,ZooKeeper 就能正常服务)。
  • 为了保证高可用,最好是以集群形态来部署 ZooKeeper,这样只要集群中大部分机器是可用的(能够容忍一定的机器故障),那么 ZooKeeper 本身仍然是可用的。
  • ZooKeeper 将数据保存在内存中,这也就保证了 高吞吐量和低延迟(但是内存限制了能够存储的容量不太大,此限制也是保持 Znode 中存储的数据量较小的进一步原因)。
  • ZooKeeper 是高性能的。在“读”多于“写”的应用程序中尤其地高性能,因为“写”会导致所有的服务器间同步状态。(“读”多于“写”是协调服务的典型场景。)
  • ZooKeeper 有临时节点的概念。当创建临时节点的客户端会话一直保持活动,瞬时节点就一直存在。
    而当会话终结时,瞬时节点被删除。持久节点是指一旦这个 ZNode 被创建了,除非主动进行 ZNode 的移除操作,否则这个 ZNode 将一直保存在 Zookeeper 上。
  • ZooKeeper 底层其实只提供了两个功能:①管理(存储、读取)用户程序提交的数据;②为用户程序提交数据节点监听服务。

ZooKeeper 特点

ZooKeeper 有哪些特点呢?具体如下:

  • 顺序一致性:从同一客户端发起的事务请求,最终将会严格地按照顺序被应用到 ZooKeeper 中去。
  • 原子性:所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,也就是说,要么整个集群中所有的机器都成功应用了某一个事务,要么都没有应用。
  • 单一系统映像:无论客户端连到哪一个 ZooKeeper 服务器上,其看到的服务端数据模型都是一致的。
  • 可靠性:一旦一次更改请求被应用,更改的结果就会被持久化,直到被下一次更改覆盖。

kafka简介

Kafka是linkedin开源的MQ系统,主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输,0.8开始支持复制,不支持事务,适合产生大量数据的互联网服务的数据收集业务。

RabbitMQ/Kafka/ZeroMQ 都能提供消息队列服务,但有很大的区别。

在面向服务架构中通过消息代理(比如 RabbitMQ / Kafka等),使用生产者-消费者模式在服务间进行异步通信是一种比较好的思想。

因为服务间依赖由强耦合变成了松耦合。消息代理都会提供持久化机制,在消费者负载高或者掉线的情况下会把消息保存起来,不会丢失。就是说生产者和消费者不需要同时在线,这是传统的请求-应答模式比较难做到的,需要一个中间件来专门做这件事。其次消息代理可以根据消息本身做简单的路由策略,消费者可以根据这个来做负载均衡,业务分离等。

缺点也有,就是需要额外搭建消息代理集群(但优点是大于缺点的 ) 。

ZeroMQ 和 RabbitMQ/Kafka 不同,它只是一个异步消息库,在套接字的基础上提供了类似于消息代理的机制。使用 ZeroMQ 的话,需要对自己的业务代码进行改造,不利于服务解耦。ZeroMQ仅提供非持久性的队列,也就是说如果宕机,数据将会丢失。

RabbitMQ 支持 AMQP(二进制),STOMP(文本),MQTT(二进制),HTTP(里面包装其他协议)等协议。Kafka 使用自己的协议。

Kafka 自身服务和消费者都需要依赖 Zookeeper。

RabbitMQ 在有大量消息堆积的情况下性能会下降,Kafka不会。毕竟AMQP设计的初衷不是用来持久化海量消息的,而Kafka一开始是用来处理海量日志的。RabbitMQ和Kafka基本上是一类东西,各有优劣,ZeroMQ只是一个网络库,不支持持久化。

基本术语

  • Topic
    Kafka中的topic其实对应传统MQ的channel,即消息管道,例如同一业务用同一根管道
  • Broker
    集群中的KafkaServer,用来提供Partition服务
  • Partition
    假如说传统的MQ,传输消息的通道(channel)是一条双车道公路,那么Kafka中,Topic就是一个N车道的高速公路。每个车道都可以行车,而每个车道就是Partition。
  • 一个Topic中可以有一个或多个partition。
  • 一个Broker上可以跑一个或多个Partition。集群中尽量保证partition的均匀分布,例如定义了一个有3个partition的topic,而只有两个broker,那么一个broker上跑两个partition,而另一个是1个。但是如果有3个broker,必然是3个broker上各跑一个partition。
  • Partition中严格按照消息进入的顺序排序
  • 一个从Producer发送来的消息,只会进入Topic的某一个Partition(除非特殊实现Producer要求消息进入所有Partition)
  • Consumer可以自己决定从哪个Partition读取数据
  • Offset
    单个Partition中的消息的顺序ID,例如第一个进入的Offset为0,第二个为1,以此类推。传统的MQ,Offset是由MQ自己维护,而kafka是由client维护
  • Replica
    Kafka从0.8版本开始,支持消息的HA,通过消息复制的方式。在创建时,我们可以指定一个topic有几个partition,以及每个partition有几个复制。复制的过程有同步和异步两种,根据性能需要选取。正常情况下,写和读都是访问leader,只有当leader挂掉或者手动要求重新选举,kafka会从几个复制中选举新的leader。
    Kafka会统计replica与leader的同步情况。当一个replica与leader数据相差不大,会被认为是一个"in-sync" replica。只有"in-sync" replica才有资格参与重新选举。
  • ConsumerGroup
    一个或多个Consumer构成一个ConsumerGroup,一个消息应该只能被同一个ConsumerGroup中的一个Consumer消化掉,但是可以同时发送到不同ConsumerGroup。
    通常的做法,一个Consumer去对应一个Partition。
    传统MQ中有queuing(消息)和publish-subscribe(订阅)模式,Kafka中也支持:
  • 当所有Consumer具有相同的ConsumerGroup时,该ConsumerGroup中只有一个Consumer能收到消息,就是queuing模式
  • 当所有Consumer具有不同的ConsumerGroup时,每个ConsumerGroup会收到相同的消息,就是publish-subscribe模式

topic中partition存储分布

Topic在逻辑上可以被认为是一个queue。每条消费都必须指定它的topic,可以简单理解为必须指明把这条消息放进哪个queue里。为了使得 Kafka的吞吐率可以水平扩展,物理上把topic分成一个或多个partition,每个partition在物理上对应一个文件夹,该文件夹下存储 这个partition的所有消息和索引文件。partiton命名规则为topic名称+有序序号,第一个partiton序号从0开始,序号最大值为partitions数量减1。

基本交互原理

每个Topic被创建后,在zookeeper上存放有其metadata,包含其分区信息、replica信息、LogAndOffset等,并使用了zookeeper watch机制来发现meta信息的变更并作出相应的动作(比如consumer失效,触发负载均衡等)

Producer端使用zookeeper用来"发现"broker列表,以及和Topic下每个partition leader建立socket连接并发送消息.
Broker端使用zookeeper用来注册broker信息,已经监测partitionleader存活性.
Consumer端使用zookeeper用来注册consumer信息,其中包括consumer消费的partition列表等,同时也用来发现broker列表,并和partition leader建立socket连接,并获取消息.

  1. Broker node registry: 当一个kafkabroker启动后,首先会向zookeeper注册自己的节点信息(临时znode),同时当broker和zookeeper断开连接时,此znode也会被删除.
    格式: /broker/ids/[0…N] -->host:port;其中[0…N]表示broker id,每个broker的配置文件中都需要指定一个数字类型的id(全局不可重复),znode的值为此broker的host:port信息.
  2. Broker Topic Registry: 当一个broker启动时,会向zookeeper注册自己持有的topic和partitions信息,仍然是一个临时znode.
    格式: /broker/topics/[topic]/[0…N] 其中[0…N]表示partition索引号.
  3. Consumer and Consumer group: 每个consumer客户端被创建时,会向zookeeper注册自己的信息;此作用主要是为了"负载均衡".

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。