程序员科普时间:Kafka 不是数据库

1,086 阅读6分钟

理解流式基础设施的使用和滥用,这一点很重要。

Kafka 是一种消息代理,在过去几年中迅速流行起来。消息代理已经存在很长时间了,它们是一种专门用于在生产者和消费者系统之间“缓冲”消息的数据存储。Kafka 已经相当流行,因为它是开源的,并且能够支持海量的消息。

消息代理通常用于解耦数据的生产者和消费者。例如,我们使用一个类似 Kafka 的消息代理来缓冲客户生成的 Webhook,然后将它们批量加载到数据仓库中。

在这个场景中,消息代理提供了从客户发送事件到 Fivetran 将它们加载到数据仓库之间的事件持久存储。

但是,Kafka 有时候也被描述为是一种比消息代理更大的东西。这个观点的支持者将 Kafka 定位为一种全新的数据管理方式,Kafka 取代了关系数据库,用于保存事件的最终记录。与读写传统数据库不同,在 Kafka 中,先是追加事件,然后从表示当前状态的下游视图中读取数据。这种架构被看成是对“数据库的颠覆”。

原则上,以一种同时支持读和写的方式实现这个架构是有可能的。但是,在这个过程中,最终会遇到数据库管理系统几十年来遇到的所有难题。你或多或少需要在应用程序层开发一个功能齐全的 DBMS,而你可能不会做得太好,毕竟一个数据库需要很多年才能做好。你需要处理脏读、幻读、写偏移等问题,还要应付匆忙实现的数据库存在的所有其他问题。

ACID 困境

将 Kafka 作为数据存储的一个最基本的问题是它没有提供隔离机制。隔离意味着在全局内,所有事务(读和写)都是沿着某些一致的历史记录发生的。Jepsen 提供了一个隔离级别指南( jepsen.io/consistency…) 。

我们举一个简单的例子来说明为什么隔离很重要:假设我们正在运营一个在线商店。当用户结账时,我们要确保他们下的订单都有足够的库存。我们是这样做的:

  1. 检查用户购物车中每个物品的库存水平。

  2. 如果某个物品没有库存,则中止结账。

  3. 如果所有物品都有库存,从库存中减去它们,并确认。

假设我们使用 Kafka 来实现这个流程。我们的架构可能看起来像这样:

Web 服务器从 Kafka 下游的库存视图读取库存,但它只能在 Checkouts 主题的上游提交事务。问题在于并发控制:如果有两个用户争着购买最后一件商品,那么只有一个用户可以购买成功。我们需要读取库存视图,并在一个单独的时间点确认结帐。但是,在这个架构中没有办法做到这一点。

我们现在遇到的问题叫做写偏移。当结账事件被处理时,从库存视图中读取的数据可能已经过时。如果两个用户同时尝试购买相同的物品,他们都将购买成功,那么我们便没有足够的库存供应给他们。

这种基于事件溯源的架构存在很多类似这样的隔离异常,让用户感到很困惑。更糟糕的是,研究表明,允许异常存在的架构也存在安全漏洞,给了黑客窃取数据的机会,正如这篇文章( www.cockroachlabs.com/blog/acid-r… )所写的那样。

将 Kafka 作为传统数据库的补充

如果你只是将 Kafka 作为传统数据库的补充,这些问题就可以避免:

OLTP 数据库负责执行消息代理不太擅长的关键任务:事件的准入控制。与将消息代理作为“触发并遗忘”事件的容器不同,OLTP 数据库可以拒绝冲突性事件,确保只接收一个具有一致性的事件流。OLTP 数据库在这一核心并发控制任务上做得非常出色——可扩展到每秒处理数百万个事务。

当使用数据库作为数据入口,从数据库读取事件的最佳方法是通过 CDC(变更数据捕获)。市场上有几个很棒的 CDC 框架,例如 Debezium( debezium.io/ )和 Maxwell( maxwells-daemon.io/ ),以及来自现代 SQL 数据库的原生 CDC。CDC 还提供了优雅的运维解决方案。在进行数据恢复时,可以清除下游的所有内容,并从(持久化的)OLTP 数据库重新构建。

不要随意构建错误的数据库

几十年来,数据库社区已经总结了一些重要的经验教训。这些教训都是在造成数据损坏、数据丢失和让用户遭受损失的情况下获得的,并为此付出了惨重的代价。如果你不小心构建了一个错误的数据库,那么你会发现自己只不过是在重新经历这些经验教训。

实时流式消息代理是管理快速变化的数据的一个很好的工具,但你仍然需要一个传统的 DBMS 来实现事务隔离。要实现一个“颠覆性的数据库”,可以使用 OLTP 数据库进行准入控制,使用 CDC 进行事件生成,并将数据的下游副本变成物化视图。

原文链接: materialize.com/kafka-is-no…

推荐阅读

MySQL从入门到进阶教程

字节跳动总结的设计模式 PDF 火了,完整版开放下载

刷Github时发现了一本阿里大神的算法笔记!标星70.5K

程序员50W年薪的知识体系与成长路线。

月薪在30K以下的Java程序员,可能听不懂这个项目;

关于【暴力递归算法】你所不知道的思路

开辟鸿蒙,谁做系统,聊聊华为微内核

看完三件事❤️

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。

关注公众号 『 Java斗帝 』,不定期分享原创知识。

同时可以期待后续文章ing🚀