打破内存数据库的 4 个神话

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

实时响应可以成就或破坏您的应用

我们所知道的世界正在以前所未有的速度变化。最佳的应用程序用户体验需要十分之一秒范围内的超快响应时间。如果将 50 毫秒计入平均可接受的 Internet 往返响应时间,这意味着您的应用程序应在剩余的 50 毫秒内处理数据并返回响应。这反过来又需要亚毫秒级的数据库响应时间,尤其是当您同时处理数千个请求时。只有最灵活但最通用的数据库才能满足这种对速度的需求。

在大数据处理场景中,必须收集洞察力并快速做出决策,内存数据库可以将处理时间从几小时或几分钟缩短到几秒钟,而无需进行复杂的优化或妥协。但是关于内存数据库有很多神话。大多数人认为它们不可靠、前后矛盾且昂贵。但最重要的是,他们认为在内存中运行任何类型的数据库都足以获得所需的速度。

误区 #1:所有内存数据库都同样快

这是不正确的。尽管大多数内存数据库都是用高效的编程语言(如 C 或 C++)编写的,但它们的响应速度各不相同,因为:

  • 不同的数据库 处理命令的复杂度 是不同的。最快的是那些以最小复杂度执行大多数命令的命令(示例:Order O(1) operations or opposite O(n) where n is the number of items in your dataset/data structure)。如果您的数据集随着时间的推移而增长并且您不想不断地重新优化查询时间,那么这一点尤其重要。
  • 查询效率 也各不相同。有时,数据库会将所有放入内存的数据视为单个 BLOB(就像 memcached 对缓存所做的那样),这是低效的——数据库需要保留查询离散值的能力,以节省内存和网络开销,并显着减少应用程序处理时间。
  • 网络流水线、协议和连接效率 各不相同。数据库需要能够为较低的上下文切换流水线命令,并快速解析请求或序列化响应。他们需要保持与数据的长期连接,以避免在 tcp 连接的设置和拆卸过程中浪费时间。
  • 单线程与多线程架构 选择存在权衡。多线程利用所有可用的计算能力,无需操作员的努力。但是这样的解决方案也需要大量的内部管理和同步,这反过来又会消耗大量的计算资源。与多线程架构相关的锁定开销会显着降低数据库性能。

单线程提供了一种非常简单的无锁执行模型,因此计算成本要低得多,但这将管理计算资源的责任转移给了操作员/用户。当然,理想的解决方案是操作员/用户不必担心计算资源管理,因为数据库管理是以一种不会占用大量资源的方式提供的。

  • 什么都不共享 vs 共享一些 vs 共享一切 架构选择会影响可伸缩性。数据库大小会随着时间的推移而增加,并且性能必须随着您添加实例而扩展。无共享模型确保每个实体(或进程)作为一个独立的单元运行,并且当进程数量增加时没有通信开销,从而实现线性可扩展性。
  • 内置零延迟分布式代理等加速组件 ,可以通过卸载大量面向网络的任务(例如连接建立/拆卸和管理大量连接)和减少TCP协议来显着提高数据库的性能高架。在某些情况下,代理可以与数据库通信,就好像它是机器上的另一个进程一样,扮演着代表许多远程客户端工作的活动本地客户端的角色。

如果吞吐量和延迟是您的主要衡量标准,那么您应该选择一个能够以一致的亚毫秒延迟和所需的最少服务器数量最大化吞吐量的数据库。

下图显示了在真实场景中运行的几个内存 NoSQL 数据库之间的性能差异。


误区 2:内存计算不可靠且不一致

大多数 NoSQL 数据库(不仅仅是内存中的数据库)在将数据提交到磁盘或副本之前向客户端提供确认 (ack)。因此,中断可能会使数据处于不一致的状态。

CAP 定理指出,任何分布式计算机系统都不能同时提供一致性、可用性和分区容错性。不同的数据库属于不同的类别,如下所示:



选择 CP 模型数据库意味着开发人员不必担心一致性,但在网络分裂事件期间不允许“写入”命令。

选择 AP 模型意味着数据库在网络分区下仍可用于“写入”和“读取”命令,但开发人员必须编写应用程序代码以确保一致性,而不是让数据库强制执行。

只需根据您的用例选择正确的数据库模型即可。

误区 3:内存计算难以扩展

有几种方法可以考虑规模。您可以通过升级托管数据库的服务器(例如添加更多 RAM 或内核)来扩大规模。或者,您可以通过向内存集群添加更多服务器来进行横向扩展。对于某些数据库,您可以在同一节点上运行同一数据集的多个切片(或分片),从而通过首先利用所有现有核心来延迟添加更多节点的需要。您还可以将跨多个服务器的内存视为一个共享池,从而能够在单节点内存的限制之外进行扩展。今天的一些内存数据库允许您以无缝的方式向上/向下或向外/向内扩展数据库,通过动态增加为数据库操作分配的核心和内存节点的数量来最大化应用程序的响应能力。

误区 4:内存计算很昂贵

任何需要快速吞吐量的用例都会提出一个问题:“特定水平的吞吐量究竟需要多少资源?”例如,使用单个 Amazon EC2 实例每秒提供 150 万次操作的内存数据库比可能不在内存中运行的替代数据库的运行成本更低(并且在每台服务器的磁盘资源方面可能更便宜),但最终使用数十台服务器来获得相同的吞吐量。

如果你的数据集运行到几个 TB 并且内存成本成为一个问题,现在有技术创新可以使用闪存作为 RAM 扩展器,使这种解决方案的成本比纯内存便宜 10 倍.请记住,闪存作为 RAM 扩展会在一定程度上影响性能,因此这里的理想技术是允许用户定义其 RAM/闪存比率以获得所需性价比的技术。 Redis Labs 的 RLEC 提供了这种类型的可配置性。

总结

内存计算选项在过去几年中已经发展成为可靠、一致、高度可扩展和廉价的。低于十分之一秒的数据库延迟和几分钟的分析处理时间正在成为事实上的行业标准。为了跟上您的竞争并提供最佳的应用程序用户体验,数据架构师必须将内存计算整合到他们的应用程序堆栈中。

注意: 在此处 下载文章中提到的独立基准测试。