如何实现多个 Kafka 集群的高可用

基于熔断机制切换主备 Kafka 集群

Posted by Ink Bai on 2020-08-14, & views

熔断机制是网关中经常用到的一种策略,那么它和 Kafka 组合在一起会产生什么化学反应呢,让我们一起来瞧一瞧。

多 Kafka 集群的高可用到底指什么?

打开 Kafka 的官网,它首先告诉你 Kafka 能做啥,其中就有高可用。

Kafka 的高可用,通俗理解就是一个 Kafka 集群不会完全挂掉,总是会有那么几个 broker 是可以工作的,在数据量比较小的时候一般 Kafka 自身的 HA 就可以 cover 住大部分的问题,但是如果数据量很大呢?

如果集群日常的流量就很大,磁盘的 IO 经常会打得很高,必然会导致响应变慢,数据大量落磁盘,数据延迟,如果可接受延迟还好,如果业务端需要极高的实时性,那么这个时候的高可用也仅仅就是「可用」了。

那么应该怎么办呢?简单,流量大就加机器呗。难就难在加多少,怎么加。

最简单的,你可以直接加到可以容纳两倍高峰期流量的机器,当然这样会导致低峰期的时候会造成一些浪费,特别是如果你有多个隔离的 Kafka 集群,综合起来的成本还是很大的。

还有另一种加机器的思路就是除了日常使用的主 Kafka 集群,启用一个额外的备 Kafka 集群。在 Hadoop 集群中,主备集群的 HA 必须保证数据同步,而 Kafka 多集群要保证数据同步难度是很大的,因为除了接收的数据保持一致,消费的 offset 也必须保持一致,复杂度很高,所以本文所说的多 Kafka 集群的 HA,指的是如果数据写入主 Kafka 集群受阻,如主 Kafka 集群负载太高,响应变慢,那么就可以分出一部分数据写入到备 Kafka 集群,实现「真」高可用。

启用一个备 Kafka 集群比直接在主 Kafka 集群上加机器的好处有哪些呢?

  1. 考虑极端情况,单集群除了负载问题也可能有其他意想不到的问题,万一真挂了或者说某些热点问题导致数据延迟了那就 GG 了,而两套 Kafka 集群同时出现问题的可能性就降低了很多。

  2. 如果你有多个独立的 Kafka 集群,那就可以让它们共用一个备集群,而不是每套 Kafka 集群都疯狂加机器。

  3. 需要临时加机器时,备集群比主集群流量小,加起来更容易,影响更小。

  4. 可以在低峰期在备集群上做一些额外的事(当然主集群你也可以这样做,就是风险更大哦)

熔断机制简介

在聊利用熔断实现多 Kafka 集群 HA 之前,让我们先简单了解下什么是熔断。

熔断一般用于网关服务中,当服务的错误率达到一定阈值时,就不再处理新的请求,新的请求会被直接拒绝掉或者走提前设定的降级策略,这种状态就叫做熔断。

下图是熔断器模式的逻辑:

服务器的健康状况 = 请求失败数 / 请求总数
熔断器开关由关闭到打开的状态转换是通过当前服务健康状况和设定阈值比较决定的:

  1. 当熔断器开关关闭时,请求被允许通过熔断器。如果当前健康状况高于设定阈值,开关继续保持关闭。如果当前健康状况低于设定阈值,开关则切换为打开状态。
  2. 当熔断器开关打开时,请求被禁止通过。
  3. 当熔断器开关处于打开状态,经过一段时间后,熔断器会自动进入半开状态,这时熔断器只允许一个请求通过。当该请求调用成功时,熔断器恢复到关闭状态。若该请求失败,熔断器继续保持打开状态,接下来的请求被禁止通过。

熔断器的开关能保证服务调用者在调用异常服务时,快速降级返回结果,避免大量的同步等待,进而导致压爆服务器资源。并且熔断器在一段时间后继续侦测请求执行结果,提供恢复服务调用的可能。

如何基于熔断切换主备 Kafka

介绍完熔断,那么这跟 Kafka 有什么关系呢?我们期待的是通过主备 Kafka 集群来实现高可用,说简单点也就是需要一个负载均衡器,能够动态分流,使主集群和备集群可以接收符合自己集群负载的流量。如何实现这个流量的动态均衡呢,这就可以通过熔断来实现。

当主集群正常时,错误率很低甚至没有错误,此时不需要熔断。当集群流量升高,错误率也达到一定值之后,我们可以依据错误率计算一个熔断率,熔断之后的流量就会进入到备 Kafka 集群,从而分摊了主 Kafka 集群的压力。

对于单个主 Kafka 集群或者是备 Kafka 集群,都有一个熔断器,根据滑动窗口来计算其熔断率:

是否熔断有两个条件:

  • 第一样本总数要达到一定量,比如总记录数要超过 10000 才是有意义的,当然具体多少量可以根据业务需要自由调节。样本太小说明量太小,这个时候并不需要在主备 Kafka 之前均衡流量,也就不需要熔断。
  • 第二超过一个预先设定的错误率阈值后才开始熔断,如规定错误率超过 1%,那么在错误率低于 1% 的时候就不会做任何操作。

当满足这两个条件后,才开始计算熔断率,也就是仅有一定概率会被熔断:

熔断率 = totalFail / totalSum / 熔断错误率阈值 / 100

例如在一个时间窗口内,总共有 10000 条记录,其中有 1000 条记录是失败记录数,如果我们设定的错误率阈值为 1%,那么熔断率就是 1000 / 10000 / 0.01 / 100 = 0.1

通过这种方式,我们分别可以得到主备 Kafka 各自的熔断率,并依此计算出主备 Kafka 集群合适的流量比例。

总结

利用熔断机制分流本质上很简单,就是一种负载均衡算法,通过熔断我们可以实现动态并且更加灵敏地感受集群当前的负载情况,同时作出调整。这种在主备 Kafka 集群之间切流的方式,给了我们除了 Kafka 本身保证的集群高可用之外,另一种实现高可用的方式。

但是还是需要根据场景灵活使用,这种方式更适用于流量大并且流量可能会有较大浮动的场景,如果日常流量就比较稳定,选择多集群其实是增大复杂度的,因为多集群也就意味着同时要消费多个。