导读
Apache Kafka可以而且应该取代数据库吗?如果是,那么能够在Kafka中存储多长时间的数据?如何在Kafka中查询和处理数据?越来越多诸如此类的问题,你可能很难找到恰当的解释,那么你可以试着从该文章中寻找答案。
Apache Kafka和Confluent的联合创始人Jay Kreps在2017年就已经解释了为什么 "在Apache Kafka中存储数据是可以的",然而,时光匆匆过去了三年,很多东西都有了改进,并增加了新的组件和功能。这篇文章从数据库的角度出发,一直谈到Kafka的核心概念,解释了数据库背后的思想和不同的功能,如存储、查询和事务,探讨了Kafka和其他数据库之间的关系和衡量标准,希望你可以从阅读中有所收获。
什么是数据库
让我们从一个很高的层面来思考 数据库
这个词,根据维基百科的说法:
数据库,又称为数据管理系统,简而言之可视为电子化的文件存储器,用户可以对文件中的数据运行新增、截取、更新、删除等操作。
数据库管理系统(DBMS)是与最终用户、应用程序和数据库本身进行交互的软件,用于采集和分析数据,DBMS软件还包括为管理数据库提供的核心设施。数据库、DBMS和相关的应用程序的总和可以称为 "数据库系统",通常情况下,"数据库 "一词也被用来松散地指代DBMS、数据库系统或与数据库相关的应用程序中的任何一个。
计算机科学家可以根据数据库管理系统支持的数据库模型对数据库管理系统进行分类。关系型数据库在20世纪80年代成为主流,这些数据库将数据建模为一系列表中的行和列,绝大多数使用SQL来编写和查询数据。到了2000年代,非关系型数据库开始流行,由于使用不同的查询语言,因此被称为NoSQL。
根据这个定义,我们知道,市场上有很多数据库,如:甲骨文(Oracle)、MySQL、Postgres、Hbase、MongoDB、InfluxDB等等。
数据库选型
数据库基础设施用于数据的存储、查询和处理,通常有特定的交付和持久性保证(又称为事务)。
从市场上所有的NoSQL和大数据产品中,我们都应该知道,并不是只有一个数据库。对于每个用例,通常是根据业务的特点选择合适的数据库:要存储多长时间的数据、数据应该有什么样的结构、你需要复杂的查询或者是仅仅通过键和值来检索数据,此外还要考虑是否需要ACID事务、精确的一次性语义等等。
例如:在你进行架构选型时就要考虑是否需要像MySQL或Postgres这样的关系型数据库、像Hbase这样的大数据批处理平台、像MongoDB这样的文档存储、像RocksDB这样的键值存储、像InfluxDB这样的时间序列数据库、像Memcached这样的内存内缓存……这些问题以及更多的问题都必须要回答。
每个数据库都有不同的特点,因此,当你问自己是否可以用Kafka来代替数据库时,你要做的是先弄清楚你的业务需求是什么,你需要用哪种数据库。
此外,你还需要对kafka进行调研,了解kafka特性,评估它能否取代的数据库。那么kafka是什么呢?
什么是Apache Kafka
先看官方是如何定义kafka的:
Kafka
是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据。
我们进行详细的分析。
Kafka是一个事件流平台
首先,Kafka不只是一个单纯的Pub/sub消息系统,它是一个事件流媒体平台,集高度解耦、可扩展性强、高可用、分布式流式处理于一身,使得它成为大数据领域和微服务领域的标配。因此,可以用以下四点对kafka进行概括:的主要原因之一是它结合了四个强大的概念:
-
发布和订阅事件流,类似于消息队列或企业消息系统;
-
容错性的数据存储系统,只要你愿意(数小时、数天、数月、永久);
-
实时事件流处理;
-
支持集成丰富的数据源和数据存储介质(无论实时、批处理还是请求响应)。
通过以上的分析,我们可以得出结论:存储是Kafka的主要原则之一,因此,根据你的需求和定义,Kafka是可以作为数据库来使用的。
Kafka Core 是一个有ACID保证的数据库吗
关于 "Kafka Core"(指的是Kafka brokers 及其分布式提交日志、复制、分区、保证排序等概念)如何与数据库的ACID(Atomicity、Consistency、Isolistency、Isolation、Durability)事务属性相匹配的讨论,我就不一一列举了。Martin Kleppmann在2018年旧金山Kafka峰会("Is Kafka是数据库吗?")上已经讨论过这个问题,而Tim Berglund("Dissolving the Problem - Making an ACID-Compliant Database Out of Apache Kafka")在技术上则稍稍逊色一些。
可以肯定的是:Kafka是一个数据库,提供了ACID保证,然而,它的工作方式与其他数据库不同。Kafka也不是要取代其他数据库,相反,它是你的工具集中的一个补充工具。
kafka的客户端
在消息传递系统中,客户端API提供了生产者和消费者发送和读取消息的功能。所有其他的逻辑都使用低级编程或附加框架来实现。
在数据库中,客户端API提供查询语言来创建数据结构,并使客户端能够存储和检索数据。所有其他的逻辑都是使用底层编程或附加框架来实现。
在事件流平台中,客户端API就像在消息系统中一样,用于发送和消耗数据。然而,与消息传递和数据库相反,客户端API提供了更多的功能。
利用Kafka API可以构建独立、可扩展、可靠的组件应用程序。因此,Kafka客户端应用程序是一个分布式系统,它可以查询、处理和存储连续的数据流。许多应用程序可以在不需要另一个额外的框架的情况下构建。
Kafka 生态系统
Kafka生态系统提供了各种组件来实现应用。
Kafka本身包括一个Java和Scala客户端API(Kafka Streams用于Java的流处理,以及Kafka Connect用于集成不同的源和汇而无需编码)。
许多其他的Kafka原生客户端API和框架都存在,下面列举了其中的一些例子:
-
librdkafka:Apache Kafka协议的C库实现,提供了生产者、消费者和管理员客户端,它在设计时考虑到了消息传递的可靠性和高性能。目前,生产者的数据超过
100万条/秒
,消费者的数据超过300万条/秒
。除了C语言库之外,它还经常被用作包装器,提供其他编程语言的Kafka客户端,如C++、Golang、Python和JavaScript等。 -
Rest Proxy:为Kafka集群提供一个RestFul接口,它可以轻松地生成和消费消息,查看集群的状态,并执行管理操作,而无需使用Kafka协议或客户端。
-
KsqlDB:一个用于Apache Kafka的事件流数据库,可以利用你对关系型数据库的熟悉程度来构建事件流应用程序。
-
Spring for Kafka:将核心的Spring概念应用于基于Kafka的消息和流媒体解决方案的开发,它提供了一个 "模板 "作为发送消息的高级抽象,包括对Kafka Streams的一流支持。其他Spring框架,如Spring Cloud Stream和Spring Cloud Data Flow,也提供了对Kafka事件流的原生支持。
-
Faust:一个用于在Python中构建流媒体应用的库,类似于原始的Kafka Streams库(但功能更有限,不那么成熟)。
-
TensorFlow I/O + Kafka插件:原生集成到TensorFlow中,用于流式机器学习(即直接从Kafka中消耗模型进行模型训练和模型评分,而不是使用另一个数据湖)。
领域驱动设计(DDD)
Kafka的客户端对于讨论可能取代数据库的重要性至关重要,因为Kafka应用程序可以是无状态的,也可以是有状态的;后者在应用程序中保持状态,而不是使用外部数据库。下面的存储部分包含了关于客户端应用如何长期、高可用的数据存储的更多细节。
了解了这些,你就明白了Kafka有强大的服务器端和客户端。很多人在评估Kafka与其他消息解决方案或存储系统相比,很多人都没有意识到这一点。
有了这一点,再加上利用Kafka的底层存储在生产者和消费者之间做真正的解耦的能力,就会明白为什么Apache Kafka会成为微服务架构的事实上的标准和骨干——不仅仅是取代其他传统的中间件,还可以利用域驱动设计(DDD)来构建客户端应用,实现解耦应用、Dumb Pipes(“愚蠢”的管道)和智能端点。
再次,为什么这对于围绕Kafka是数据库的讨论很重要?对于你创建的每一个新的微服务,你应该问自己:我的微服务中真的需要一个 "真正的数据库 "后端吗?是为了节省在开发、测试、运营、监控等方面的复杂性和成本?
通常情况下,答案当然是肯定的。我看到越来越多的应用,在Kafka应用中直接保持状态是更好、更容易,或者两者兼而有之。
数据在kafka中保留多久
简而言之,数据可以在Kafka中保存多久就保存多久,Kafka甚至提供了一个保留时间为-1的配置选项,这意味着永不删除。
如果你觉得永不删除太简单粗暴了点,那么你就要对你的系统做一个完整的梳理:你需要考虑Kafka中介的成本和可扩展性,你应该使用HDD还是SDD?或者甚至要不要基于闪存的技术?Pure Storage写了一个很好的例子,利用闪存存储,利用3个生产者和3倍复制,每秒写入500万条消息。这取决于你需要存储多少数据,以及你需要多快的访问数据并能够从故障中恢复。
《纽约时报》的Apache Kafka发布是用Kafka永远存储数据的著名例子。Kafka被用来存储《纽约时报》曾经发布的所有文章,并取代了他们基于API的方式。Streams API 是用来将已发布的内容实时反馈给各种应用和系统,让我们的读者可以使用。
直到现在,我们还只是在谈论最常用的Kafka功能。基于日志的存储,保留时间和磁盘附加到代理上。然而,你还需要考虑Kafka的其他功能,才能对Kafka基础设施中的长期存储进行完整的讨论。契约化主题、分层存储和客户端存储。所有这些功能都可以很快改变你对Kafka、其用例和架构的思考方式。
数据压缩存储
日志压缩确保Kafka将始终保留单个主题分区的数据日志中每个消息键的最后一个已知值。它解决的是一些用例和场景,比如在应用程序崩溃、系统故障后恢复状态,或者在运行维护期间应用程序重启后重新加载缓存等。因此,日志压缩并没有保留时间。
显然,为了权衡利弊,日志压缩并不能保留所有事件和完整的变化顺序。为此,你需要使用普通的Kafka主题,并有特定的保留时间。
或者你可以使用-1来永远保存所有数据。这里的大的缺点是磁盘成本高,操作和可扩展性更复杂。
分层存储
Kafka的分层存储降低了成本(由于更便宜的对象存储),提高了可扩展性(由于存储和处理之间的分离),并且简化了操作(由于简化了和更快的再平衡)。
下面是一些在Kafka中长期存储完整日志的例子(而不是利用压缩的主题)。
-
新的消费者,例如,一个完整的新的微服务或替换现有的应用程序。
-
容错处理,例如在发生错误时重新处理数据,以修复错误并再次处理事件。
-
合规/法规处理。由于规则原因对已经处理过的数据进行重新处理;可能是非常老的数据(例如制药业:10年的数据)。
-
查询和分析现有事件。不需要另一个数据存储/数据湖;ksqlDB(位置优先,但要知道各种限制);Kafka-native分析工具(如Rockset与Kafka连接器和对Tableau等的完全SQL支持)。
-
机器学习和模型训练。使用不同的机器学习框架和不同的超参数或不同的机器学习框架来进行模型训练。
有状态的kafka生产者
如上文所述,Kafka不仅仅是服务器端。你可以在Kafka客户端构建高可用和可扩展的实时应用。
基于RocksDB实现有状态的Kafka
通常情况下,这些Kafka客户端应用必须是有状态的。Kafka Streams和ksqlDB为此利用了RocksDB(你也可以直接使用内存内存储或者用其他存储替换RocksDB;不过我在实际应用中从未见过后者的选择)。RocksDB是一个用于运行关键任务工作负载的关键值存储,它针对快速、低延迟存储进行了优化。
在Kafka Streams应用中,这解决了抽象访问本地稳定存储而不是使用外部数据库的问题。如果使用外部数据库,每次处理一个事件都需要外部通信/RPC,这在事件流架构中是一个明显的反模式。
RocksDB允许用户将精力集中在系统的其他领域的设计和实现上,可以放心地依靠RocksDB来访问稳定的存储。RocksDB在硅谷的几家公司进行了实战测试,并在许多著名的数据库如Apache Cassandra、CockroachDB或MyRocks(MyRocks)的引擎盖下使用。
事件流数据库KsqlDB
Kafka Streams 和 ksqlDB - Kafka的事件流数据库 - 允许构建有状态的流媒体应用;包括强大的概念,如加入、滑动窗口和状态的交互式查询等。下面的例子显示了如何构建一个有状态的支付应用。
客户端应用程序将数据保存在自己的应用程序中,用于实时连接和其他数据关联。它结合了STREAM(不可更改的事件)和TABLE(像关系型数据库中的更新信息)的概念。
请记住,这个应用是高度可扩展的。它通常不只是一个单一的实例。相反,它是一个分布式的客户端实例集群,工作时提供高可用性和并行化数据处理。即使发生了什么故障(VM、容器、磁盘、网络),整个系统也不会丢失数据,24小时不间断地继续运行。
正如你所看到的那样,很多问题都需要回答,各种功能都要考虑到,要想在Kafka中存储多长时间、在哪里存储数据,必须做出正确的决定。
在Kafka中长期存储数据的一个很好的原因是为了能够在以后的时间点使用这些数据进行处理、关联或分析。
kafka消费者处理
Kafka提供了不同的选项来消耗和查询数据。
Kafka中的查询可以是PUSH(即连续处理和转发事件)或PULL(即客户端请求事件,就像你知道的从你最喜欢的SQL数据库中请求事件一样)。
消费者应用pull模式
Kafka客户端从中间件那里拉来的数据,这使生产者、中间件和消费者解耦,使基础设施具有可扩展性和可靠性。
Kafka本身包括一个Java和Scala客户端来消费数据。然而,Kafka客户端几乎可以用于任何其他编程语言,包括广泛的语言,如C、C++、Python、JavaScript或Golang,以及异国语言,如RUST。此外,Confluent提供了一个REST代理。这允许从任何支持该标准的语言或工具通过HTTP(S)消耗事件。
应用程序有不同的选项来消费来自Kafka代理的事件。
-
连续消费最新事件(实时或批处理)。
-
只消耗特定的时间框架或分区。
-
从一开始的所有数据。
Kafka的查询局限性
上述描述的Kafka查询功能都不像你心爱的Oracle数据库或Elasticsearch那样强大!
因此,Kafka不会取代其他数据库,它是相辅相成的。Kafka背后的主要思想是连续处理流式数据,并有额外的选项来查询存储的数据。
Kafka作为数据库对于一些用例来说,Kafka已经足够好了。但是,Kafka的查询能力对于其他一些用例来说,Kafka的查询能力还不够好。
这时,Kafka通常被用作一个中心流平台,一个或多个数据库(和其他应用)利用自己的技术,构建自己的物化实时视图。
这个原理通常被称为 "将数据库内化为外",这种设计模式允许使用合适的数据库来解决合适的问题,Kafka就是在这些场景中使用的:
-
作为可扩展的事件流平台,进行数据整合。
-
用于不同生产者和消费者之间的解耦。
-
用于处理背压。
-
用于持续处理和关联传入的事件。
-
用于实现在其他数据库中创建和更新物化视图。
-
允许直接向Kafka进行交互式查询(根据用例和使用的技术)。
kafka能取代原有的数据源吗
对于很多场景来说,如果以中心事件流平台为核心的单一流平台就很好。Kafka提供了一个基于事件的实时基础设施,它是可扩展的,可以将所有的生产者和消费者解耦。然而,在现实世界中,像ERP系统这样的东西,即使它通过Kafka将数据推送到企业的其他部分,往往也会保持主导地位。
这是完全没有问题的,Kafka作为中心流平台,并不会强迫你让它成为每个事件的主导系统。对于一些应用和数据库来说,在与Kafka集成后,现有的的数据源仍然是主导作用。
这里的关键点是,你的单一源不应该是存储数据的数据库,比如说在Hadoop或AWS S3这样的数据湖中,系统闲时存储数据。这样一来,你的中心存储就是一个缓慢的批处理系统。你不能简单地将实时消费连接到它。另一方面,如果一个事件流平台是你的中心层,那么你可以把它摄取到你的数据湖中,进行数据的闲时处理,但你也可以很容易地添加另一个实时消费者。
kafka能否整合数据分析工具
通过Kafka访问海量的事件流数据,引发了用户对交互式、实时仪表盘和分析的强烈兴趣,其想法类似于在传统数据库(如Oracle或MySQL)之上使用Tableau、Qlik或Power BI,以及使用Impala、Presto或BigQuery的Hadoop等批处理框架,在传统数据库之上建立的,用户希望提出问题并快速得到答案。
利用Rockset,一个基于RocksDB的可扩展的SQL搜索和分析引擎,并与Tableau等BI和分析工具相结合,可以直接查询Kafka日志。使用ANSI SQL,没有任何限制。在规模上,在实时的情况下,这应该是个检验你的数据湖战略的好时机。
Kafka的事务支持
Kafka提供了端到端的处理保证、持久性和高可用性,可以构建最关键的业务应用。我在不同的行业中,包括银行、电信、保险、零售、汽车等行业,都看到过很多基于Kafka构建的关键任务基础架构。
我想把交付保证和正确性作为消息系统和数据库的关键特性,重点放在交付保证和正确性上。在很多应用中,事务处理是需要保证数据不丢失和确定性的行为。
数据库中的事务处理是将信息处理分为单个的、不可分割的操作,称为事务。每一个事务必须作为一个完整的单元成功或失败;它不可能只有部分完成。许多具有事务处理能力的数据库(包括两阶段的Commit/XA事务)都不能很好地扩展,而且很难操作。
因此,许多分布式系统只提供 "至少一次语义"。
kafka中的actly-once语义(EOS)
Kafka是一个分布式系统,提供各种保证交付。不同的配置选项,可以实现at-least-once、at-most-once和actly-once语义(EOS)。
Exactly-once语义就是人们将其比作数据库事务。其思想是相似的:你需要保证每一个产生的信息都被消耗和处理过一次。很多人认为,这在Kafka中是不可能实现的,因为在分布式系统中,单个的、不可分割的操作可能会失败。而在Kafka中,很多人认为这一点是不可能实现的。在Kafka的世界里,很多人提到了著名的黑客新闻讨论 "你不可能有精确的一次交付 "以及类似的Twitter对话。
在2017年,"不可思议的事情 "发生了。Apache Kafka 0.11 增加了对 Exactly-Once Semantics(EOS)的支持。注意,它并没有刻意包含 "事务 "这个词。因为它不是一个事务。因为在分布式系统中,事务是不可能的。但是,结果是一样的:每个消费者对每一个产生的消息都是精确地消费一次。
详细信息请查看:https://www.confluent.io/blog/exactly-once-semantics-are-possible-heres-how-apache-kafka-does-it
简而言之,EOS包括三个特点:
-
Idempotence。Exactly-once 在每个分区的顺序语义都有一次;
-
Transactions:事务,在多个分区之间进行原子写入。
-
在Apache Kafka中的精确的一次流处理。
Matthias J. Sax在2018年伦敦Kafka峰会(Kafka Summit 2018)上对EOS进行了精彩的讲解,详细请查看连接:
https://www.confluent.io/kafka-summit-london18/dont-repeat-yourself-introducing-exactly-once-semantics-in-apache-kafka
EOS的工作方式与数据库中的事务不同,但最终提供的结果是一样的。它可以通过配置开启。顺便说一下,相对于完全-一次语义,EOS的性能惩罚并不大---通常情况下,端到端处理速度要慢10到25%。
EOS不仅仅是Kafka内核和相关的Java/Scala客户端的一部分。大多数Kafka组件支持精确的一次交付保证,包括:
-
一些(但不是全部)Kafka Connect连接器。例如AWS S3和Elasticsearch。
-
Kafka Streams 和 ksqlDB,用于流式ETL或业务应用中的数据处理精确一次的数据。
-
非Java客户端.librdkafka---许多Kafka客户端的核心基础,各种编程语言的核心基础--最近增加了对EOS的支持。
Kafka会取代现有数据库吗
一般来说,不!但你应该经常问自己。除了Kafka之外,你还需要另一个数据存储吗?有时是的,有时不是。我们讨论过数据库的特点,以及什么时候Kafka就足够了。
每个数据库都有特定的特性、保证和查询选项。使用MongoDB作为文档存储,使用Elasticsearch作为文本搜索,使用Oracle或MySQL作为传统的关系型用例,或者使用Hadoop作为大数据湖来运行map/reduce作业的报表。
这篇文章希望能帮助你在下一个项目中做出正确的决定。
然而,我们常常遇到的问题不是kafka取代哪些数据库,通常情况下,Kafka和数据库是相辅相成的,我们该如何将kafka和这些数据库进行整合使用,下面将对这部分进行讲解。
Kafka和其他数据库之间的集成
Apache Kafka包括Kafka Connect,一个连接Kafka与外部系统(如数据库、键值存储、搜索索引和文件系统)的框架。使用Kafka Connect,你可以使用现有的连接器实现常见的数据源和汇,将数据移入和移出Kafka。
这包括许多连接到各种数据库的连接器。要从源系统中查询数据,可以通过拉出事件(如使用JDBC连接器),或者通过Chance-Data-Capture(CDC,如使用Debezium连接器)推送事件。Kafka Connect还可以写到任何一个数据存储,包括各种关系型、NoSQL和大数据基础架构,如Oracle、MongoDB、Hadoop HDFS或AWS S3等。
你可以查看:Kafka Connect入门 和 Kafka Connect深入理解 进行学习。
Kafka对其它数据库的补充
Apache Kafka是一个数据库。它提供了ACID保证,被数百家公司用于关键任务部署。然而,在很多情况下,Kafka与其他数据库相比,Kafka是没有竞争力的。Kafka是一个事件流平台,可以在零停机时间和零数据丢失的情况下,实时进行消息传递、存储、处理和规模化集成。
基于这些特点,Kafka经常被用作中心流集成层。物化视图可以由其他数据库为其特定的用例构建,如实时、时间序列分析,近乎实时地摄取到文本搜索基础设施中,或者长期存储在数据湖中。
综上所述,如果有人问你Kafka是否可以替代数据库,那么这里有不同的答案:
-
Kafka可以将数据永远的存储在一个持久的、高可用的方式提供ACID保证;
-
在Kafka中,有不同的选项可以查询历史数据;
-
Kafka原生的附加组件,如ksqlDB或分层存储,使Kafka在数据处理和基于事件的长期存储方面比以往任何时候都更加强大;
-
可以利用Kafka客户端(微服务、业务应用)构建有状态的应用程序,而不需要另一个外部数据库;
-
不是替代现有的数据库,如MySQL、MongoDB、Elasticsearch或Hadoop等数据库;
-
其他数据库和Kafka是相辅相成的,必须为一个问题选择合适的解决方案,经常会有专门定制的物化视图从基于中心事件的基础架构中实时创建和更新;
-
Kafka和数据库之间的双向pull和基于push的双向集成有不同的选择,可以实现互补。
作者 | Kai Wähner
编辑 | Gavin
原文 | https://dzone.com/articles/is-apache-kafka-a-database-the-2020-update
- THE END -