有经常关注本博客的同学应该知道以前我就写过关于 Kafka 的文章,不过那是关于入门的,所以这篇文章就定位上来说肯定不是入门的了。如标题所言,这篇文章将解读一下 Kafka 的特性,并且就特性的实现原理进行一个探讨,但是这个探讨还是停留在理论层面,没有深入的代码层面进行分析,这个可以期待后续的文章。

在我们查看关于 Kafka 的资料的时候,我们可以看到很多关于 Kafka 的描述,这里我就总结了其中 4 个比较重要的特性进行介绍:

  1. 可靠性(Reliability)
  2. 伸缩性(Scalability)
  3. 持久性(Durability)
  4. 高性能(Performance)

可靠性

什么是可靠性,这个概念和可用性有点像,但是不完全一样,我根据书本《分布式系统原理与范型》中的解释区分,拿电脑来说,如果一台电脑不能一天到晚都运行,假设电脑运行了 12 个小时就会 CPU 温度过高,需要关机一小时,那么它的可用性就是 12/13,但是以可靠性来说,我们就不能说它可靠性是 12/13,只能说他是不可靠的,哪天基友约通宵副本都玩不起,怎么能叫可靠呢?

这就是可靠性,那么 Kafka 是如何保障可靠性呢?

  1. Kafka Broker 挂了

    假设我用三台机器运行着一个 Kafka 集群,那么我们这里假设挂了一台(粗暴点,把它的电源拔了),但是 Kafka 还是可以可靠得给我们提供服务,这就依赖于 Kafka 的 replication,也就是所谓的副本,在 Kafka 中,我们可以以 partition 为基本单位,设置 topic 的副本份数,然后 Kafka 会以我们设置的备份份数对 partition 进行备份,从而保障在某一台或多台机器故障之后仍然可以无错误得提供服务。

  2. Consumer 断了

    假设我们 Kafka 服务器没挂,但是客户端挂了,重新连接上去之后,会不会丢失掉还没处理的数据?这个 kafka 是可以给我们一些保证的,Kafka 的基础保证是它不会轻易得删除数据,即使是我们有消费者消费了数据之后,这个特性可以让我们多个消费者可以同时互不干扰得访问同一个 Topic 的数据。

    同时,Kafka 还支持对于同一组客户端在同一个 partition 上保留消费的位置,也就是说假如我消费了 topic1 的 partition1 上的一部分消息之后,断了重连,那么可以接着继续消费,而不需要从头开始消费。这里需要注意的是,对于同个 topic 的同个 partition,Kafka 同一个消费者组只能有一个消费者消费这个 partition。

伸缩性

所谓的伸缩性就是说,Kafka 可以根据我们的业务量动态得变化 broker 的数量。假设我们的业务量比我们想象中的少,那么我们可以减少一些 Kafka 集群的机器;如果业务量比我们想象中的大,那么我们可以快速得加一些 kafka 集群的机器,而这些操作都可以单独执行,不影响整个集群的正常运行。

kafka 之所以能够实现动态伸缩,这个得归功于 zookeeper,由于 kafka 使用 zookeeper 配置管理集群中机器的状态,那么也就能够让 Productor 和 Consumer 及时感知到服务器的变化,从而作出相应的响应。

持久性

不同于 Redis/RabbitMQ 这类内存消息队列,Kafka 的消息是持久化到磁盘中的,所以,这也在一定程度上保证了服务的可靠性。

根据 Kafka 的官方文档所说,当消息被发送到 broker 的时候,会根据 partition 的计算规则选择 partition,然后这条消息会被 append 到指定的 partition 中。

高性能

高性能就很好理解了,也就是 Kafka 可以提供很快速的发布消息和订阅消息速度,同时也能在大流量的情况下轻松处理,根据官方的介绍,在这个配置的机器下的性能为:

服务器配置

各状态下性能

可以看到 Kafka 的性能表现是非常强劲的,同时也可以看到 replication 的变化对性能影响不是很大,同时 producer 的增加会大大提供性能的利用,为什么会这样呢?主要原因有以下:

  1. partition 是均分到不同的 broker 的

    因为 partition 是均分到不同的 broker 的,同时 productor 和 partition 关系是固定的,所以当我们将 productor 从一个提升到 3 个的时候,那么理论上速度是可以提升 3 倍的;

    但是,需要注意的是,当我们继续提升 productor 的数量的时候,理论上速度是不会再增加了,反而有可能会减少。

  2. partition 存储是顺序的

    前面已经说过,当一个消息需要保存到 partition 时,是顺序 append 到 parition 上的,这样的话我们可以在磁盘上保证连贯性,从而在读写的时候保证了速度。

Reference

  1. Kafka Document
  2. Benchmarking Apache Kafka
  3. Reliability with Kafka
  4. Kafka深度解析