《如何從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學院為您提供專業教程。