kafka为什么不采用读写分离的架构实现

Posted DDSHANG

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kafka为什么不采用读写分离的架构实现相关的知识,希望对你有一定的参考价值。

最近被问到一个问题,kafka既然也是一个分主从的集群架构,为什么不采用读写分离的实现,刚刚听到这个问题的时候我有点懵,读写分离,为什么要读写分离?

于是硬着头皮回答了一些,

1.读写分离的架构会让实现更加的复杂,可能引入未知问题和破坏结构的清晰

2.读写分离可能导致数据不一致的情况

后来看了一些别人的观点后觉得,这个回答虽然有点道理却并不算完整,虽然对一些其他的观点我也不完全认同。

在此我不会从原理和源码的角度发表长篇大论,只是单纯的从我自己的角度写一点思考。

关于这个问题,一些提到比较多的回答其实也包含了上面两点,另外还有成本和收益不匹配说

我觉得从这个角度来说是可以的,

从使用场景来说,kafka并不需要或者这样的需求很小,所以并没有选择读写分离。

首先我们需要知道为什么要读写分离,主要是为了缓解同一个节点的压力,我们知道一般情况下写是一个排他的行为,可能需要涉及加锁等比较重的操作,但是读一般来说都是可以共享的,可以同时发生的操作。

再说读写分离的应用场景,主要用于解决一次写入,多次读取的,读和写的比例相差比较大,为了提高系统的可用性和处理能力,会考虑使用读写分离架构。

说回kafka的使用场景,一般是作为消息中间件使用,写入kafka的消息不能被修改,所以只能一次写入,kafka消息会被不同的消费者读取,也可能被反复的读取,看起来符合多次读取的条件,不过一般对kafka消息的读取都是在刚刚写入完成之后,或者写完相对比较短的一段时间之后,因为消息有过期时间,一般不会,也不能读取很早之前的数据,所以kafka的使用不能算一次写入多次读取的场景。

有人说,读写分离是一种对于设计不合理的架构的一种补充,kafka因为架构设计非常优秀所以不用这种补充,这种说法是有点过于彩虹屁了。

另外一个角度是负载均衡,

读和写都是通过Leader,topic的partition是比较均匀分布在各节点的,对于个节点的负载相对比较均衡。不过需要注意的是,生产者和消费者都可以指定特定的分区读写,同时因为消息分区算法的原因,也可能导致分区内数据不均匀导致负载不均匀。

总结一下,从成本和收益的角度来考虑这个问题是合理的,所以原因可以是

1.引入读写分离会导致架构更复杂

2.可能会有数据不一致的问题

3.在kafka的设计场景下,并没有太多读写分离的需求

4.topic的partition划分是按leader均匀分配在各节点的,读写都走Leader的话,可以一定程度做到负载均衡

为什么Kafka不支持读写分离

在 Kafka 中,生产者写入消息、消费者读取消息的操作都是与 leader 副本进行交互的,从 而实现的是一种主写主读的生产消费模型。数据库、Redis 等都具备主写主读的功能,与此同时还支持主写从读的功能,主写从读也就是读写分离,为了与主写主读对应,这里就以主写从读来称呼。Kafka 并不支持主写从读,这是为什么呢?

从代码层面上来说,虽然增加了代码复杂度,但在 Kafka 中这种功能完全可以支持。对于 这个问题,我们可以从“收益点”这个角度来做具体分析。主写从读可以让从节点去分担主节 点的负载压力,预防主节点负载过重而从节点却空闲的情况发生。但是主写从读也有 2 个很明 显的缺点:

  • (1)数据一致性问题。数据从主节点转到从节点必然会有一个延时的时间窗口,这个时间 窗口会导致主从节点之间的数据不一致。某一时刻,在主节点和从节点中 A 数据的值都为 X, 之后将主节点中 A 的值修改为 Y,那么在这个变更通知到从节点之前,应用读取从节点中的 A 数据的值并不为最新的 Y,由此便产生了数据不一致的问题。
  • (2)延时问题。类似 Redis 这种组件,数据从写入主节点到同步至从节点中的过程需要经 历网络→主节点内存→网络→从节点内存这几个阶段,整个过程会耗费一定的时间。而在 Kafka 中,主从同步会比 Redis 更加耗时,它需要经历网络→主节点内存→主节点磁盘→网络→从节 点内存→从节点磁盘这几个阶段。对延时敏感的应用而言,主写从读的功能并不太适用。

现实情况下,很多应用既可以忍受一定程度上的延时,也可以忍受一段时间内的数据不一 致的情况,那么对于这种情况,Kafka 是否有必要支持主写从读的功能呢?

主写从读可以均摊一定的负载却不能做到完全的负载均衡,比如对于数据写压力很大而读 压力很小的情况,从节点只能分摊很少的负载压力,而绝大多数压力还是在主节点上。而在 Kafka 中却可以达到很大程度上的负载均衡,而且这种均衡是在主写主读的架构上实现的。我们来看 一下 Kafka 的生产消费模型,如下图所示。

技术图片

在 Kafka 集群中有 3 个分区,每个分区有 3 个副本,正好均匀地分布在 3个 broker 上,灰色阴影的代表 leader 副本,非灰色阴影的代表 follower 副本,虚线表示 follower 副本从 leader 副本上拉取消息。当生产者写入消息的时候都写入 leader 副本,对于图 8-23 中的 情形,每个 broker 都有消息从生产者流入;当消费者读取消息的时候也是从 leader 副本中读取 的,对于图 8-23 中的情形,每个 broker 都有消息流出到消费者。

我们很明显地可以看出,每个 broker 上的读写负载都是一样的,这就说明 Kafka 可以通过 主写主读实现主写从读实现不了的负载均衡。上图展示是一种理想的部署情况,有以下几种 情况(包含但不仅限于)会造成一定程度上的负载不均衡:

  • (1)broker 端的分区分配不均。当创建主题的时候可能会出现某些 broker 分配到的分区数 多而其他 broker 分配到的分区数少,那么自然而然地分配到的 leader 副本也就不均。
  • (2)生产者写入消息不均。生产者可能只对某些 broker 中的 leader 副本进行大量的写入操 作,而对其他 broker 中的 leader 副本不闻不问。
  • (3)消费者消费消息不均。消费者可能只对某些 broker 中的 leader 副本进行大量的拉取操 作,而对其他 broker 中的 leader 副本不闻不问。
  • (4)leader 副本的切换不均。在实际应用中可能会由于 broker 宕机而造成主从副本的切换, 或者分区副本的重分配等,这些动作都有可能造成各个 broker 中 leader 副本的分配不均。

对此,我们可以做一些防范措施。针对第一种情况,在主题创建的时候尽可能使分区分配 得均衡,好在 Kafka 中相应的分配算法也是在极力地追求这一目标,如果是开发人员自定义的 分配,则需要注意这方面的内容。对于第二和第三种情况,主写从读也无法解决。对于第四种 情况,Kafka 提供了优先副本的选举来达到 leader 副本的均衡,与此同时,也可以配合相应的 监控、告警和运维平台来实现均衡的优化。

在实际应用中,配合监控、告警、运维相结合的生态平台,在绝大多数情况下 Kafka 都能 做到很大程度上的负载均衡。总的来说,Kafka 只支持主写主读有几个优点:可以简化代码的 实现逻辑,减少出错的可能;将负载粒度细化均摊,与主写从读相比,不仅负载效能更好,而 且对用户可控;没有延时的影响;在副本稳定的情况下,不会出现数据不一致的情况。为此, Kafka 又何必再去实现对它而言毫无收益的主写从读的功能呢?这一切都得益于 Kafka 优秀的 架构设计,从某种意义上来说,主写从读是由于设计上的缺陷而形成的权宜之计。

 

以上是关于kafka为什么不采用读写分离的架构实现的主要内容,如果未能解决你的问题,请参考以下文章

为什么Kafka不支持读写分离

干货|为什么Kafka不支持读写分离

阿里面试,为什么Kafka不支持读写分离

Kafka为什么不支持读写分离得原因?-干货

Kafka竟然不支持读写分离!今天才知道!

基于 Kafka 与 Debezium 构建实时数据同步