《如何从MongoDB迁移到DynamoDB?》要点:
本文介绍了如何从MongoDB迁移到DynamoDB?,希望对您有用。如果有疑问,可以联系我们。
相关主题:非关系型数据库
保留数据是当今大多数Web服务的核心,选择数据库系统是最重要的决策之一.在选择数据库技术后,这是在生产中最难替换的技术之一.
本文中我们将探讨MongoDB以及迁移到DynamoDB的做法,并分享办理方案来应对这一迁移中的挑战.
Auth0 Extend的数据需求是什么?
Auth0 Extend是一种托管服务,可整合到SaaS产品中来支持自定义代码(客户用以扩展SaaS平台编写的代码)的编写和执行.你可以将Auth0 Extend视为webhook的更好替代,它是包括编写和无服务器执行环境的webhook.
Auth0 Extend使用存储来保留有关webtask(代码、加密配置、元数据)、CRON工作(其计划、状态、执行历史)以及不同环境中可用NPM模块(其状态、构建历史等)的信息.除了基本的CRUD操作,Auth0 Extend还会在持久存储器上面部署专门的队列语义.在我们技术堆栈的分布式环境中,实现所需的要求需要使用更高级的DB结构.
MongoDB蜜月期
早在2014年,当我们开始Auth0 Webtask(Auth0 Extend产品的无服务器技术)的工作时,通常会选择Mongo作为存储层.Mongo已经用在Auth0身份产品中,而且,我们已经开始在内部构建该技术的专业技能.
在发展初期,Mongo的关键功能是模式灵活性.
除非你发送空间探测器到海王星再回来,不然你不太可能使用预定的数据模式来开始软件项目.
选择让你可简单根据项目进展调整模式的DB系统是实现快速进展的关键.
Mongo就是这样的系统.我们不断添加集合、修改模式、优化索引以有效操作数据,直到Auth0 Extend平台趋于稳定和成熟时,Mongo的灵活性都发挥着重要作用,赞助我们快速发展.
墙壁上的裂缝
随后,MongoDB仍然给我们带来很大赞助,那么,问题在哪里呢?Mongo带来很多工作,太多工作.
在Auth0早期阶段,我们尝试选择几家SaaS提供商来提供托管Mongo解决方案.在最后,没有哪个提供商可完全满足我们对数据位置、可靠性、监控和控制水平的要求.因此,我们开发了内部功能来维持Mongo开发,虽然这个办法在有限数量部署运行良好,但这种办法限制我们将Auth0 Extend产品扩展到所有AWS地区.对于小团队来说,在每个AWS地区托管自己的Mongo实例不太可能实现.
在这一点上,我们做出了战略调整,重新考虑外部基础设施的存储层,并更广泛地了解可用选项.
究竟我们在Auth0 Extend的核心竞争力是通过自定义代码扩展SaaS平台,而不是管理我们的存储.
由于AWS是我们主要云提供商,我们开始研究AWS中托管存储选项.我们很快发现DynamoDB,它可很好满足我们的要求.它快速且可靠,加之最新添加的内存中缓存和自动扩展,它成为非常有吸引力的选择.但问题依然存在:我们能否将Mongo中数据拜访语义复制到DynamoDB中吗?
MongoDB vs. DynamoDB
没有哪两个数据库系统完全相同,即使两者都标榜自己是文档存储系统.MongoDB和DynamoDBY让你可使用任意模式存储类似JSON数据,甚至有AWS迁移工具可赞助执行Mongo到DynamoDB的数据自动导入.
Mongo和DynamoDB之间的主要区别在于后者对你如何有效索引和拜访数据有更多规定.
如果你正在为事务数据寻找存储系统,那么关键是所有数据库操作可被优化以非常有效地执行.与DynamoDB相比,MongoDB在索引数据方面提供更大灵活性.因此,从MongoDB迁移到DynamoDB的主要挑战是,在DynamoDB设计你的索引战略以支持所需的拜访模式.下面我们将展示我们实现这一目标所使用的技巧.
DynamoDB索引
如果你是DynamoDB新手,并在考虑从另一个DB系统进行数据迁移,笔者强烈建议你首先阅读DynamoDB开发人员指南.
DynamoDB中的存储都是表的形式,每个表都是具有本身索引、容量和可扩展配置的独立单元,DynamoDB表类似MongoDB集合.
虽然DynamoDB允许使用任意模式存储数据,与Mongo相比,对数据创立索引更为有限:
每个DynamoDB表必需具有唯一的主索引.它由一个或两个字段组成:强制分区密钥(散列密钥)和可选分类密钥(范围密钥).该分区密钥指定DynamoDB内数据位置.出于性能原因,建议分区密钥的值广泛分布.分类密钥作为分区内的次级密钥.
每个DynamoDB表最多可以用5个当地次级索引.这些索引必须共享相同分区密钥作为表的主索引,但具有不同的分类密钥.当地次级索引不一定是唯一.
每个DynamoDB表还可最多拥有5个全局次级索引,这种索引类似于“对等表”.全球次级索引包括与主表相同的文档,并将最终与主表一致.然而,你可以为全局次级索引定义全新的分区和分类密钥.
DynamoDB支持三种主要方式来查找数据进行读取或修改:getItem操作检索单个条目.query操作检索条目列表,基于分区密钥和可选过滤条件的精确匹配.最后,scan操作让你更灵活地在任何字段表达条件,但它扫描表的全部内容,所以会无效.毋庸置疑,如果你想要利用索引进行有效查找,query是不错的选择.
考虑到这些DynamoDB情况,让我们来看看从Mongo迁移的示例.
案例一:CRUD和List
在Auth0 Extend,webtask存储在单个MongoDB集合中.每个webtask可使用{webtask_container},{webtask_name}作为唯一标识,这在webtask技术开发中是唯一标识.然而,Mongo数据库被设计为支持多个部署,基于此,为了在单个数据库获得webtask的唯一标识符,必需使用{deployment_key},{webtask_container},{webtask_name}三元组.
为了支持Webtask的有效执行和管理,该系统必需支持以下操作:
特定webtask的有效CRUD
在给定webtask容器中列出所有webtask
在MongoDB中支持这两种情况非常简单.对{deployment_key},{webtask_container},{webtask_name}的复杂索引支持特定webtask这两种有效的CRUD,以及特定容器中所有webtask列表(在这种情况下,query仅使用索引的 {deployment_key},{webtask_contaier} )例如:
迁移到DynamoDB的挑战在于,DynamoDB表中复杂主索引只能支持两个字段.以下是你如何设计索引来有效支持CRUD和列表操作:
分区密钥是{deployment_key}/{webtask_container}形式的符合字符串
分类密钥为{webtask_name}.
特定webtask的CRUD操作指定完整主密钥.列表操作可通过DynamoDB的query操作有效部署,query操作仅指定分区密钥作为其密钥条件的部门.这样做逻辑上可将结果缩小到{deployment_key}和{webtask_container}:的webtask.
请注意,DynamoDB中的query操作允许对分类密钥表达更灵活的条件.例如,除了完全匹配分区密钥外,你还可有效匹配分类密钥的前缀.
案例二:原子查找和更新
自动更新文档是在分布式系统中部署很多更高级操作的基础.在Auth0 Extend中,我们在CRON子系统中部署独占作业预留时依靠Mongo的 findOneAndUpdate 操作,并依靠它来在写入webtask存储时检测冲突.
考虑一下,Mongo的 findOneAndUpdate 如何用于确保仅当文档数据库版本与调用者最后读取版原形匹配时才更新:
DynamoDB的UpdateItem操作支持类似语义,并包括Key子句选择条目使用其主密钥更新,以及 ConditionExpression 以确保该条目在更新前具有预期版本:
ConditionExpression让你可确保表中特定文档在自动更新前处于所需要的状态.类似子句被称为 FilterExpression ,它可指定为query操作以缩小选择的条目.后者必需谨慎使用,因为对于匹配密钥条件的每个条目,过滤器表达式都以强力方式进行评估.
Case 3: CRON作业
Auth0 Extend支持计划作业.计划作业就像常规webtask,除了它们会由Auth0 Extend运行时依照预配置的计划自动调用外.计划作业保留在数据库中,并且,必须在以下情况下有效被访问:
·管理API对CRON作业执行基本CRUD和List操作.CRUD操作必要CRON作业使用 {deployment_key},{webtask_container},{webtask_name} 主密钥进行唯一标记,List操作范围限定为{deplyment_key},{webtask_container}对.
·CRON守护程序必须能够识别要运行的下一个作业.每个CRON作业都有{next_available_at}属性,其中包括EPOCH时间—该作业下一次运行的时间.为了选择下一个运行的作业,守护程序必须选择具有最小{next_available_at} t值的CRON作业,该值也小于或等于现在.此选择在特定{deployment_key}范围执行.
Mongo使用两个索引.其中一个是复杂索引{deployment_key},{webtask_container},{webtask_name},它支持CRUD和List操作:CRUD使用完整密钥来标志CRON作业,而List使用前两个段:{deployment_key},{webtask_container}.
CRON守护法式使用 {deplyment_key},{next_available_at}另一个索引来有效选择下一个运行的作业:
迁移这种使用模式到DynamoDB必要仔细规划才能有效支持所有操作.
CRUD和List操作可以由包括{deployment_key}分区密钥和{webtask_container}/{webtask_name}.形式的复合分类密钥的复杂主密钥来支持.CRUD操作然后可完整指定该主密钥的所有组件,而List操作可指定确切的分区密钥以及分类密钥的前缀条件:
与上述案例一中描述的模式相比,为什么我们要复杂化主密钥的结构?这样做是为了使我们能够有效支持相同表中的另一个索引,守护程序需要用来选择下一个运行的作业.鉴于该主密钥的分区密钥是{deployment_key}值,我们可使用相同分区密钥创建当地次级索引,{next_available_at}值作为分类密钥.
通过使用该索引(被称为work_queue),我们可有效查询下一个运行的CRON作业:
这样做的原因是特定分区密钥内的文档使用该索引的分类密钥排序,所以,限定成果集到一个文档,自然会返回最小next_available_at值
通过全局次级索引也可实现类似的效果.使用当地次级索引的优势在于,全局索引维护成本更高:每次写入到表都需要写入到全局索引,从而增加操作总成本.
如果你喜欢填字游戏,那你也会喜欢设计DynamoDB索引,特别是当地次级索引.
接下来?
我们成功地将Auth0 Extend数据层从MongoDB迁移到DynamoDB,这让我们可在所有AWS地区支持我们的产物,而这在我们自主托管Mongo时期非常难以完成.
虽然我们已经实现“代码完成,所以测试通过”的过渡阶段,我们知道这只是旅程的开始.
编写软件和运行服务之间还有很大距离,未来的工作包含:
设计强年夜的跨区域故障转移机制
对新客栈的稳定化和性能调优
欢迎参与《如何从MongoDB迁移到DynamoDB?》讨论,分享您的想法,维易PHP学院为您提供专业教程。