Azure Cosmos DB 设计模式
本文是Microsoft员工Andrei Zaichikov的Azure Cosmos DB设计模式文章的日本语翻译。
※翻译工作已经得到作者的事前同意。
※原始文章并非来自Microsoft官方文章,而是由博客作者提出的个人观点。
图片。自动移动的锯木厂。Rodion Zaichikov。
Azure Cosmos DB 设计模式
免责声明:所有观点和建议均为本人个人意见。请勿仅凭文字相信,建议您进行测试并根据您自己的情况来决定。在应用于正式环境之前,请三思而行 ?
一切皆依赖于使用情景。
你好。
今天,我将讨论使用Cosmos DB构建解决方案的几种重要且有效的方法(或设计模式)。这些方法本质上是结构化的,并使用其他服务和工具来优化Cosmos DB工作负载。
一般来说,我不太喜欢在成熟之前进行优化。此外,在尝试了一些可悲的尝试之后(请猜一下那时我正在阅读的书籍),我对模式变得谨慎起来了。
然而,我在过去的8年中,在使用包括Azure Cosmos DB、Mongo DB、Cassandra和其他一些技术的NoSQL项目中收集了这些技巧。这些模式主要是为那些已经使用了现有Cosmos DB的优化和最佳实践,并已经获得了接近最佳结果的人提供帮助的。
即使只计划在Cosmos DB上构建一些东西,考虑到这些方法并在设计和构建应用程序时,以便以后可以使用它们是明智的。
我想重申一遍,在开始之前,微软的建议仍然有效,并且我希望强调可以取得良好的结果。
-
- 目的のプロファイリング
-
- キャッシング
-
- ストリーミング
-
- データオフロード
-
- 一時的な構造を使用して大規模なイベントを処理する
-
- コアデザインブロックとしてのデータ移行スクリプト
-
- テスト/開発環境の設計
- データ移行エンジン
总结起来,我会简单地解释为什么要使用Cosmos DB来回答这个问题。
开始之前
在探讨「高级」优化案例和策略之前,我们先总结一下微软提供的一些最佳实践。
-
- 以下是設計 Cosmos DB 工作負載時應遵循的一些非常好的實踐,這些內容被概述在這個視頻中。
-
- 一些額外的推薦項目(應在集合和應用程序級別應用):
優化開發和測試
理解 Azure Cosmos DB 的計費方式
優化吞吐成本
優化儲存成本
優化查詢成本
優化多區域 Azure Cosmos 帳戶的成本
以下是可用於進一步優化成本的 Cosmos DB 功能:
Cosmos DB 變更提要
Cosmos DB 自動調整
Cosmos DB 分析存儲
所以,如果您浏览这些资料后发现它们是相当复杂的案例,那么就立即开始吧。
为了达到目的的个人剖析
大多数情况下,工作负载都是为了特定的目标而存在的。哦,理想情况下就是这样……总之。
这幅画中展示的机制是一把自动运转的链锯(由我儿子Rodion设计,还未在LinkedIn上发布)。
重点是使用这个模型来整理稳定、可预测、高效的数据生命周期。
假设我们拥有游戏和其他B2C应用程序。通常,我们向不同的客户群体提供服务。其中包括免费客户,标准客户和高级客户等类型。
明显地,这些客户拥有相似的数据模型,但数据量差异极大,并且对处理此数据的方式(即不同的服务)和不同的 SLA 有不同要求。如果只有一个集合,会是什么情况呢?
所有的客户都将保存在一个单一的集合中。假设我们的目标是减少全球高级客户的等待时间。我们应该做些什么呢?我们使用了MultiMaster2技术。稍等片刻,因为这只是一个单一的集合(即一套集合),所以无论是高级用户还是免费用户,对于所有用户的消费都需要支付费用,对吧?是的,好处是全球所有客户的延迟时间都减少了,这将引起免费用户的注意,并导致他们购买高级订阅服务?
季节过去,收藏逐渐庞大起来。其中混合了一切。看起来如果是个游戏,我们的高级用户比起标准用户和免费用户会有更多的战利品、物品和历史记录。然而,由于所有用户都从同一个服务分区结构中获得服务,因此在同一个收藏中,不同层次的用户的消费模式重叠会带来一些负面影响。
我们来把这件事简单化吧。作为高级用户,我在我的库存中收集了10,000把剑。现在,我想一次性地搜索它们,以向妻子展示我的大部分工资去了哪里。
我可能会消耗相当数量的RU来保存数据所在的分区(请注意,每个分区都有特定的RU限制)。同样地,当有大量的免费用户通过数据库访问时,例如市场营销活动,情况也是如此。关键是,这些访问模式非常不同(少量项目,小规模请求),但会与高级用户可能受到限制和等待时间较长的情况相重叠。
如果不将过时的用户设置为TTL过期,那么当有大规模的营销活动时,这些过时的用户只会占据存储空间,可能会严重影响整个解决方案的性能。原因是RU通过Cosmos DB均匀分布到所有分区上,导致大量过时数据会影响分区的数量。
因此,更合适的方案是根据特定的使用模式来配置和配置各种层次的个别结构(集合,集合的集合)。此外,可以构建数据生命周期(例如,基于迁移脚本)以便让客户在不同层次之间进行移动。如下图所示。
这种解决方案看起来很复杂,但不仅能够应对同一集合中的不同使用模式的技术复杂性,还可以对成本和服务水平进行收集分析。它可以为高级用户提供服务,并确保对免费或非活跃用户的费用保持抑制。
时间的基本资料
作为针对特定目的的个性化分析的特殊情况,时间分析是其中之一。时间分析的方法之一是通过收集实时数据(每5到10分钟)以及每日和每月的数据,并使用变更源来有效地管理数据的生命周期。
有时候我们会看到,在特定时间到期(例如每天)时,会动态地添加新的集合。通过这种方法,我们可以减少与读取相关的请求单元(RU),同时保持写入请求单元(RU)的数量保持不变。这样一来,我们只需要在需要时进行读取的扩展。此外,由于可以在以后查询,并且可以将访问频率较低的数据转储到Cosmos DB分析存储中,因此无需修改应用程序以使用针对冷数据的额外服务。
借款
在 NoSQL PaaS(平台即服务)的世界中,顾客需要为每个请求付费。此外,在特定情况下,这些请求可能被用于重复读取。例如,假设有一个存储在 Cosmos DB 集合中的字典(比如游戏中的物品)。
因此,如果只是直接從 Cosmos DB 集合中進行查詢這些項目,您將為每個請求支付費用。因此,假設在先前提到的遊戲中擷取與 10,000 把劍相關的資訊時,(在最差的情境下)有可能耗費 10,000 RU 而需花費一段時間。如果同一個請求被數千個使用者使用,這個集合的 RU 將急劇增加。
我的一个客户使用了32个请求来进行单用户认证,并且对AppFormsTemplate集合发起了30个请求。在这种情况下,认证过程非常耗时。
有更好的方法可以以更低的成本实现相同的功能,就像你想象的那样。
为了减少使用RU的数量来获取相同的信息,可以研究不同的缓存工具和策略。通常情况下,缓存优先方法是默认选项,无论使用的是什么工具。主要原因是Cosmos DB提供了足够高速的查找性能,并且使用缓存的主要原因是为了降低RU成本。
在特定情况下,预先填充缓存也是有效的(尤其是在特定数据被使用的情况下)。
流媒体
根据情况不同,读取和写入可能以非常快的速度到达,需要立即捕获。一个很好的例子是游戏或设备的遥测数据。在这种情况下,我们可以检查设备的动态,并将其保存为一个特定时间窗口的文档。
假设根据每个设备每分钟获取100个字节的数据,并以20分钟的间隔进行汇总。如果直接将数据导入 Cosmos DB,则请求模式如下:
-
- 通过单个请求读取100字节文档-20次写入x 5RU x 3间隔=每个设备每小时300RU。
-
- 需要读取、汇总和推回文档。因此,直接使用变更反馈或API是最合理的方法。对于读取(每个独立的读取),20次读取x 1RU(默认会话一致性级别时)x 3间隔=每个设备每小时60RU。
- 在进行聚合后,还需要将聚合文档写回消耗额外的5-10RU至Cosmos DB。
作为另一种方法,您可以在 Cosmos DB 之前部署 Event Hub,然后使用 Azure Functions 或 Azure Stream Analytics 来进行一些聚合或快速分析,然后再将数据导入 Cosmos DB。这样一来,您将无法读取和写入数据到 Cosmos DB,最终可以优化 RU。
数据卸载
大多数最新的 NoSQL 数据库都是针对传统关系数据库在应对特定模式的困难而创建的,这个模式就是大规模的引用。例如,当需要检索一个用户(以购物车为例)的一个文档,并且需要以物理上可能的最快速度执行操作时。这就是采用 NoSQL 的第一个实际理由之一。目前,NoSQL 数据库在许多方面都非常出色,但通常依赖于特定工作负载的特点。
在 Cosmos DB 中也是一样的 – 在引用方面非常高效,可以提供预聚合的数据,并且在多区域部署方面非常高效(但在自己动手解决方案中非常复杂)。然而,同时,对于没有任何限制的 WHERE 子句和执行大规模时间序列分析,它并不是非常高效。
相当长的时间里,将数据卸载的唯一方式是通过使用Cosmos DB的变更Feed进行自己的实现。我个人觉得它非常高效、出色,并且是非常强大的技术的一部分,但是自己的实现并非所有人都会同意的方式。
为了解决这个问题,微软引入了新的 Synapse Link 功能,将数据转移到 Azure Synapse Analytics,从而可以利用前所未有的功能来进行大规模读取。这样一来,就可以避免在 Cosmos DB 上执行多个大规模查询,并且还可以大幅降低服务的运行成本。
在数据离线和时序模型操作方面,还有另一个最适合的服务,即Azure Data Explorer(ADE)。该服务可以直接与Event Hub进行集成(作为摄取引擎),或者通过自定义代码与Cosmos DB进行变更数据流的集成。
通过数据卸载,可以实现以下功能:
-
- Cosmos DB デプロイメントの実行率を下げる
-
- 限られた WHERE 句を使用した高速な参照とクエリによる利益を獲得する
-
- たとえば、次のような専用エンジン(集約、結合、複雑なクエリ)のフルスケールの読み取り機能をお楽しみください。Azure Synapse Analytics と Azure Data Explorer
- たとえば Azure Synapse Analytics と Azure Data Explorer のような、特化したエンジンのフルスケールの読み取り機能(アグリゲーション、ジョイン、複雑なクエリ)を楽しむことができる
以下的图表展示了所有的方法。
使用临时构造处理大规模活动(LSE)
假设你是一家游戏公司,正在准备在Microsoft Store、Steam、AppStore和其他平台上开始促销活动或全新积极的营销活动的电子商务应用程序。我们可以想象到需要比平常更大规模的活动场地。
在后端处理这种事件的简单方法是将相关的 Cosmos DB RU 的规模扩大到较高的数值,以满足不断增长的需求。在多种情况下,这种方法可能完全有效,但如果需要扩容超过10倍以上的容量增加,可能会在事件结束后面临性能下降的风险。
换句话说,原因是RU均匀分布在分区之间,所有分区都可以维持最大10,000 RU的性能。例如,设置了20,000 RU,并且每个分区的性能为10K,这是没有问题的。假设现在需要将2个分区扩展到100个,并且需要扩展到1,000,000 RU。如果事件结束后,特别是分区策略不能完全随机化/均匀分布到文档上,可能会出现严重的性能问题。要么保持足够的RU来维持每个分区的性能,要么迁移到新的集合。
当然,在出现问题时有处理选项 ? 这种方法的主要工具是监控脚本和数据迁移脚本(稍后会解释)。
更好的方法是使用临时表来处理LSE。
为了处理大规模活动,使用临时表的想法相当简单。在实际活动之前,预配到集合中所需的RU数量,并在等待时进行缩容,如果代码遇到了著名的429错误(”请求过多”),则立即逐步进行扩容。
所有从事件转移到临时集合的流量可能会重复使用“字典”集合。实际上,如果事件只持续24小时,则为了处理/保护LSE,需要花费最多24小时以上的时间。一旦LSE结束,借助客户独有的脚本或更改提要(取决于卸载时间和事件时间),可以以非常高效益的方式将数据从LSE集合移动到主要集合,后续处理几乎没有任何影响。
设计测试/开发环境
在一些项目中,我遇到了一个解决方案,其中包含了数百个被主要视为字典的小型数据集合。这些集合被缓存,但同时也非常昂贵。为什么呢?主要原因是因为这些集合是基于容器模型进行规划的,每个集合至少分配了400个RU(实际上每个集合分配了约1000个RU)。当乘以字典的数量时,开销变得巨大。
在这里值得注意的是,这些集合没有积极地被使用(开发环境),开发团队为每个过时的集合支付了每秒200次(1000 RU)的写入费用。
好处是减轻措施非常简单-在这种情况下,通过将数据库迁移到经过配置的模型上,问题得到了解决。
在正式环境中,请注意数据库的已设置集合(在 Cosmos DB 中称为容器)的行为与在单独配置下的集合有所不同。在迁移到正式环境之前,强烈建议在已设置的容器上测试解决方案(特别是重试和错误处理)。
作为核心设计模块之一的数据迁移脚本。
严格来说,在NoSQL数据库中,数据迁移经常发生。这有多个原因,其中主要原因是需要重新分配数据来实现最佳的性能结果/修复性能问题。
当有一个包含各种不同物品的大量集合,或者当出现了错误的分片键3,或者希望改变数据位置时,可能需要使用这样的脚本在Cosmos DB中操作。这将非常有用,因为通过这种方式,可以处理与其他NoSQL数据库可能面临的相同问题。例如,当需要更改分区键或需要合并大量分区时,或者需要拆分集合时,可以迁移到另一个容器中。
通常情况下,这些脚本需要在零停机时间的迁移中实施。一些提供实用解决方案的客户通过以下方式实施它们:
-
- 应用程序会尝试从目标(Sink)容器中读取。
a. 如果从Sink读取失败,则应用程序会将查询重新路由到源容器,并标记移动到源容器内的项目。在这里,错误处理非常重要。
应用程序始终会将数据写入Sink容器。
一旦项目被标记,该项目就会被推送到Cosmos DB变更Feed。定制的迁移脚本(由Cosmos DB变更Feed处理库支持的专用应用程序或Azure函数)会从变更Feed获取项目并将其写入Sink容器。同时,还会标记源集合中的项目已迁移,最坏的情况是这里可能会出现一些竞争(冲突)解决问题。
清理脚本负责从Sink容器中删除已标记为已迁移的项目。
一旦迁移完成,可以立即删除源集合和应用程序错误处理的路由信息。
总结来说
在这篇文章中,我们解释了一些复杂的方法来优化Cosmos DB。在这些讨论之后,你可能会想问一个合理的问题:”为什么需要Cosmos DB?”
然后,有几个答案(当然,全部取决于使用情况?):
-
- まず、Azure エコシステムには、大規模な検索のための優れたツールはありません。買い物かご、リーダーボード、セッション、デバイスの状態など、文字通り何でも構いません。グローバルフットプリントを追加することで、世界的に非常に低いレイテンシを顧客に提供するソリューションが得られます。
-
- 第 2 に、Cosmos DB は半構造化データを格納および配布するための優れたツールです。他にもいくつかのサービスがありますが、どれも他の Azure サービスとのネイティブな統合を行っていません。Azure Functions、Jupiter Notebooks、ダウンストリーミング用の変更フィード、Azure Synapse Link – そのほか何でもありです。
-
- 3 番目 – Cosmos DB はシンプルであることです – Cosmos DB を正しく設計し、目的に合わせて使用すれば、非常に大規模で複雑なタスクを解決するための効率的で非常に有用なツールになります。
- さらには、すべてのもの(または現在のところほとんどすべて)をスクリプト化してコードとして扱うことができるので、人生を面白くしてくれます ?
请记住经验法则-所有请求都会产生成本,包括所有数据库。唯一的区别是,Cosmos DB明确设置了成本。这是非常公平的。
请尽情享受使用Cosmos DB!
关于翻译
如果对笔者的翻译内容有任何修改或更正之处,请向我提出编辑请求。