暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【探索 Redis 功能】使用数据库扩展应用程序的技术——缩放

原创 小小亮 2023-02-23
433

缩放是使用数据库完成的最困难的任务之一。本文解释了缩放是如何工作的,在幕后。

这是探索 Redis 功能的第二篇文章。第一部分分享了开始使用 Redis 的基本数据类型和模型。

应用程序增长。随着应用程序吸引更多用户,存储所创建信息的数据库也会吸引更多用户,无论是销售交易还是收集的科学数据。更大的数据集需要更多的资源来存储和处理该数据。另外,随着越来越多的用户同时使用该系统,数据库需要更多的资源。

当您的应用程序变得流行时,它需要扩展以满足需求。如果一个应用程序很慢,没有人会留下来——无论如何都不会愿意。

如果你需要扩展,庆祝它是一个好问题!但这并不能使过程变得简单。缩放有多种可能的选择,每一种都需要不同程度的复杂性。在这里,我们将扩展作为一般挑战和专门针对Redis 数据库进行讨论,并关注使用 Redis Enterprise 的高级扩展。

缩放概念

缩放是一个多维问题,有几个不同的解决方案。

垂直扩展涉及增加数据库的资源。通常,这涉及将数据库移动到功能更强大的计算机或更大的实例类型。

“更多”是关键词。与任何硬件选择一样,您会考虑更强大的处理器、更多内存和/或更多网络带宽。您必须在它们之间找到一个平衡点,以最佳地提高数据库的性能和它可以支持的并发用户数,更不用说优化您的硬件预算了。

垂直缩放中的一个要素是调整数据库可用的 RAM 量。对于 Redis,RAM 限制了数据库可以存储的数据量,因此这是一个重要的考虑因素。

垂直缩放通俗地称为向上缩放或向下缩放这取决于您是向上移动到功能更强大的计算机还是(在极少数情况下)向下移动到功能较弱的计算机。

水平扩展涉及将额外的计算机节点添加到操作数据库的实例集群,而不更改任何单个节点的大小或容量。水平扩展也称为向外扩展(当您添加节点时)或向内扩展(当您减少节点数时)。

根据其实施方式,水平扩展还可以提高数据库的整体可靠性。它消除了单点故障,因为您增加了可在故障转移情况下使用的节点数量。然而,水平扩展也会增加时间和精力(因此成本),因为您需要更多节点(因此更多故障点)来保持数据库功能。

换句话说,垂直扩展增加了单个实例或节点的大小和计算能力,而水平扩展改变了节点或实例的数量。

假设您拥有或可以获得更大的计算机或实例,垂直扩展是提高数据库性能的一种简单方法。它通常可以在云中轻松实现,而不会影响应用程序或数据库架构。

只要您知道自己在做什么,复杂性并不是一件坏事。

正确完成后,水平缩放可为您的数据库和应用程序提供更大的增长空间。这个方案在应对性能瓶颈方面有很多历史:只需投入更多硬件即可!

然而,水平缩放通常比垂直缩放更难实现。添加额外的节点意味着更多的复杂性。这些节点是只读节点吗?读/写主节点?活跃的大师?被动大师?您的数据库和应用程序架构的复杂性可能会急剧增加。

但是,只要您知道自己在做什么,只要选择正确,复杂性并不是坏事。

有几种方法可以实现水平缩放,每种方法都有不同的优点和缺点。选择正确的模型对于构建数据存储架构很重要。Redis 支持许多水平缩放选项。有些在 Redis 开源 (OSS) 中可用,有些仅在 Redis Enterprise 中可用。

分片的基础知识

分片是一种提高数据库整体性能以及增加其存储和资源限制的技术。这是一种相对简单的水平缩放技术。

通过分片,数据分布在不同的分区或节点上。每个节点只保存整个数据库中存储的一部分数据。在 Redis 的情况下,处理键/值输入,并将数据存储在分片中。

当向数据库发出请求时,它会被发送到分片选择器,分片选择器会选择合适的分片来发送请求。在 Redis 中,分片选择通常由代理实现,该代理查看所请求数据的键,并根据键将请求发送到适当的分片实例。

分片选择算法是确定性的,这意味着对给定密钥的每个请求总是转到同一个分片。只有该分片具有给定数据密钥的信息,如图 1 所示。

图 1. 通过分片进行横向扩展

分片是扩展数据库容量的一种相对简单的方法。例如,通过向 Redis OSS 实施添加三个分片,您几乎可以将数据库的性能和存储限制提高三倍。

但是分片并不总是那么简单。选择一个能够有效平衡所有节点之间流量的分片选择器可能需要进行调整。分片还会降低应用程序可用性,因为它增加了对多个实例的依赖性。如果管理不当,单个实例的故障可能会导致整个数据库崩溃。那会导致糟糕的一天工作。

Redis 集群解决了这些问题,也让分片更容易实现。如果出于存储容量或性能的原因需要重新分片以重新平衡数据库,则数据将物理移动到新节点。

应用程序对分片选择器算法的了解可以允许应用程序在分片之间执行更好的整体平衡,但代价是增加了复杂性。

分片效率仅与所使用的分片选择器算法一样好。应用程序对分片选择器算法的了解可以允许应用程序在分片之间执行更好的整体平衡,但代价是增加了复杂性。

Redis OSS 中的集群由集群主导,客户端库具有集群感知能力。本质上,分片选择器是在客户端库中实现的。这需要客户端支持集群协议。

在 Redis Enterprise 中,服务器端代理用于实现分片选择器并为集群服务器端提供支持。代理充当水平扩展的 Redis 实例之间的某种负载均衡器。

集群是横向扩展的常见解决方案,但它有利也有弊。从好的方面来说,分片是一种快速扩展应用程序的有效方法,它被用于许多大型、高度扩展的应用程序中。此外,它开箱即用。

另一方面,集群需要额外的管理。你需要知道你在做什么。单个大键会造成难以或无法补偿的不平衡。

Redis 集群消除了许多分片的复杂性。它允许应用程序专注于更有效地扩展大型数据集的数据管理方面。它提高了写入和读取性能。

最终,它的工作效果取决于应用程序使用的访问模式。

读取副本

另一个水平缩放选项是只读副本。顾名思义,只读副本的重点是提高读取数据的性能,而不考虑将数据写入数据库所花费的时间。前提是检索数据比更改数据或添加新数据要常见得多。

在一个简单的数据库中,数据存储在单个服务器上,对数据的读写访问都发生在该服务器上。使用只读副本,服务器数据的副本存储在辅助服务器上,称为只读副本。每当更新数据时,副本都会从主服务器接收更新。

每个辅助服务器都有一个完整的数据库副本。因此,当应用程序发出读取请求时,该请求可以发送到任何只读副本服务器。这意味着可以同时处理更多的读取请求,从而提高可扩展性和整体性能。

只读副本不能提高写入性能,但可以显着提高读取性能。

但是只读副本有局限性,这取决于多种因素,例如数据库使用的一致性模型,或者您需要应对的网络延迟。

只读副本不能提高写入性能,但可以显着提高读取性能。但是,这确实需要您考虑应用程序的写入密集程度。对主数据库的数据库写入传播到只读副本需要一些时间。这种称为 skew 的延迟会导致在主服务器更新副本服务器时旧数据返回到应用程序延迟只是很短的一段时间,但有时这些延迟很关键。根据您自己的情况,这可能是问题,也可能不是问题,但在设计系统时请注意该问题。

想想写入数据库的过程。

  • 当您更新信息或添加新数据时,只对主数据库实例执行写入。那是神圣不可侵犯的;所有写入都必须转到一个主数据库实例。
  • 然后,该主实例向所有只读副本发送一条消息,指示数据库中的哪些数据已更改,并使只读副本能够更新其数据副本以匹配主副本。

由于所有数据库写入都经过主实例,因此在添加额外的只读副本时不会提高写入性能。事实上,当您添加新的只读副本时,写入性能可能会略有下降。那是因为 master 现在有一个额外的节点,它必须在发生写入时通知它。通常,这种影响并不显着,但肯定不是零影响。

考虑图 2 中的插图,它显示了一个由三个服务器组成的 Redis 实现。对 Redis 数据库的所有写入都是对单个主数据库进行的。这个单一的主人将更改数据的更新发送到所有副本。每个副本都包含存储的 Redis 数据库的完整副本。

然后,当应用程序想要检索数据时,对 Redis 实例的读取访问可以发生在集群中的任何服务器上。负载均衡器负责路由各个读取请求,它使用多种负载均衡算法中的一种来引导流量。(有几种负载均衡算法,包括循环法、最少使用法等,但它们不在本次讨论的范围内。)

图 2. 具有只读副本的水平可扩展性

使用只读副本的另一个好处是提高了可用性。如果只读副本崩溃,负载均衡器会将流量重定向到另一个只读副本。如果写入主机崩溃,您可以将其中一个只读副本提升为主机角色,这样系统就可以保持运行。

只读副本是一种易于实现的水平可扩展性模型,该方法提高了可用性,对应用程序的影响很小或没有影响。

双活

主动-主动复制或主动-主动集群是一种提高更高数据库负载性能的方法。

与只读副本一样,主动-主动(也称为多主复制)依赖于具有多个节点的数据库集群,数据库副本存储在所有节点上,负载均衡器分配负载。

然而,对于双活复制,读写请求都分布在多个服务器上,并在所有节点之间进行负载平衡。性能提升是有意义的,因为可以处理大量请求,并且处理速度更快。

请注意,Redis OSS 不直接支持 Active-Active 复制。如果事实证明这是适合您需求的扩展架构,您将需要 Redis Enterprise。但这里的重点是解释计算机科学技术,无论你从哪里得到它(包括自己构建它,如果你有那种时间)。

使用 Active-Active 复制,读取传播的发生与上一节中描述的完全相同。

当应用程序写入一个节点时,此数据库写入会传播到系统中的每个主节点。发生这种情况的方式有很多种,例如:

  • 应用程序可以强制写入所有主机。
  • 写入代理可以分发写入。
  • 接收到写调用的主节点可以将请求转发给其他非接收主服务器。

图 3 说明了一个数据库实现,该集群包含三个服务器。每个服务器都包含所有数据的完整副本。任何服务器都可以处理对数据库中任何数据的任何类型的数据请求——读取或写入。

图 3. 主动-主动复制

当负载均衡器将写入请求定向到数据库主实例时(例如在本例中),它会将更新发送到所有其他复制实例。如果将写入发送到任何其他节点,则该节点将以类似方式将更新发送到所有其他复制实例。

但是当发送两个请求来更新同一个数据值时会发生什么?

在单节点数据库中,请求是序列化的,更改按顺序发生,最后的更改通常会覆盖以前的更改。

但是,在主动-主动模型中,这两个请求可能会到达不同的主机。然后主服务器可以向其他主服务器发送冲突的更新消息。这称为写入冲突。

在写入冲突的情况下,应用程序需要确定保留哪些数据库写入,拒绝哪些。这需要某种类型的解析算法,涉及应用程序逻辑或数据库规则。

此外,由于更新是异步发送到每个节点的,因此数据滞后可能会导致一个节点与另一个节点略微不同步。即使这种不匹配只是持续很短的一段时间,这也是一个问题。开发人员必须注意应用程序会考虑这种潜在的延迟,以免影响操作。这类似于只读副本的问题,但可能更复杂。

除了提高性能之外,这种水平可伸缩性模型还提高了整体数据库可用性。如果单个节点发生故障,其他节点可以弥补这一不足。但是,由于每个节点都包含数据的完整副本,因此通过添加额外的服务器不会影响数据库的存储限制。

该模型的代价是增加了应用程序在处理冲突数据时的复杂性。

Redis Enterprise 的主动-主动地理分布

Redis OSS 本身不支持任何形式的多主冗余。

但是,Redis Enterprise 执行主动-主动地理分布,它提供主动-主动多主机冗余。

然后 Redis Enterprise 的 Active-Active Geo-Distribution 更进一步。它使各个集群能够位于地理分布的位置,但在它们之间复制数据。看一下图 4。

图 4. 跨地域的主动-主动复制

这使得 Redis 数据库可以在地理上分布,以支持在不同地理位置运行的软件实例。

在此模型中,多个主数据库实例位于不同的数据中心。这些可以位于不同地区和世界各地。个人消费者通过应用程序连接到离他们的地理位置最近的 Redis 数据库实例。Active-Active Redis 数据库实例随后在多主控模型中同步,以便每个 Redis 实例始终拥有完整且最新的数据副本。

Redis Enterprise 的 Active-Active Geo-Distribution 具有用于有效处理写入冲突的复杂算法,包括实施无冲突的复制数据类型 (CRDT),以保证最终的强一致性并使复制同步过程更加可靠。应用程序仍然必须意识到并处理数据滞后和写入冲突,因此这些问题不会成为问题。

什么适合你?

您需要让您的应用程序运行得更快,并支持它们的数据库的额外负担。幸运的是,正如本文所展示的,您有很多缩放技术的选择。每个对应用程序可用的存储空间量和系统资源都有不同的影响。

您最终选择的技术取决于许多因素,包括您公司的目标、您的软件要求、您 IT 部门人员的技能、您的应用程序架构以及您愿意承担的复杂程度。


原文标题:Techniques for Scaling Applications with a Database

原文作者:Lee Atchison

原文链接:https://thenewstack.io/techniques-for-scaling-applications-with-a-database/

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论