高度敏感應用程序的遷移

dpcg2771 8年前發布 | 5K 次閱讀 數據庫 Cassandra

本文是Netflix計費系統遷移至云中系列文章的后續,詳細介紹了將計費應用程序和數據存儲從本地數據中心遷移至AWS云的技術細節。

你可能已經從早前發布的 Netflix云遷移博客文章 中了解到,Netflix的所有流媒體基礎結構現已完全在云中運行。隨著Netflix規模不斷擴大,尤其是 Netflix Everywhere 業務即將正式登場,我們已經意識到計費系統遲早也需要遷入云中,因為現有的本地系統已經無法繼續擴展了。

毫無疑問,在不中斷業務的情況下遷移高度敏感的應用程序和重要數據庫是一項意義深遠的工作,與此同時我們還將繼續構建新的業務功能和服務。

計費系統的一些重要用途和面臨的挑戰包括:

  • 計費團隊負責管理整個公司的重要財務數據。我們每天會通過用戶的付費訂閱、禮品卡、信用額度、退款等行為生成大量數據,這些數據將匯總至財務部門并創建成報表交給公司會計。為確保每天的收入情況可以準確記錄,我們在日常處理流程中實施了嚴格的SLA。處理管線的任何延遲都是無法接受的。

  • 計費系統對數據丟失持零容忍態度。

  • 大部分情況下,現有數據使用了一種關系型模式的結構,因此需要通過事務確保這類數據實現“全有或全無(all-or-nothing)”的行為。換句話說,我們的運維必須符合ACID(原子性、一致性、隔離性、持久性)要求。但某些情況下還必須讓這些數據實現跨區域高可用,同時確保不同區域間復制的延遲最小化。

  • 計費系統與公司的DVD業務相集成,而DVD業務與在線流播業務使用了截然不同的體系結構,這也大幅增加了集成工作的復雜度。

  • 支付團隊還希望向Netflix客戶服務代理提供數據支持,幫助他們回答會員提出的有關計費操作的問題。因此迫切需要向客戶支持人員提供此類數據的概括性視圖。

當我們著手進行該項目時,計費系統是這樣的:

  • 數據中心內部署2個Oracle數據庫 – 一個存儲客戶訂閱信息,另一個存儲發票/支付數據。

  • 多個基于REST的應用程序 – 為www.netflix.com和客戶支持應用程序的調用提供服務。這些應用程序主要執行CRUD(創建、讀取、更新、刪除)操作。

  • 3個批處理應用程序:

    • 服務續訂 - 這個每天運行一次的作業會掃描所有客戶信息以確定當天需要計費的客戶,并通過這些客戶的訂閱計劃、折扣等信息確定需要計費的金額。

    • 訂單和支付處理 - 通過一系列批處理作業為需要續訂的客戶創建發票,并負責在發票生命周期內的不同階段處理有關發票的任務。

    • 營收報表 - 這個每天運行一次的作業會檢索計費數據并生成Netflix財務部門需要的報表。

  • 一個計費代理應用程序(位于云中) - 用于將Netflix在云中的其他應用程序的調用路由至數據中心。

  • 使用老版本格式的Weblogic隊列負責不同過程之間的通信。

本次項目的目標在于將所有這一切都搬入云中,不在數據中心內運行任何計費應用程序或數據庫。但所有操作不能影響業務的正常運轉。我們的前路十分艱巨!

規劃

我們制訂了一個三步規劃:

  • 第1步 – 服務新落地國家的計費系統直接從云中運行,并將所產生的數據同步回數據中心,供原有批處理應用程序繼續使用。

  • 第2步 – 對面向用戶的數據進行建模,以實現最終一致性并且不再需要符合ACID特性,將這些數據持久保存在Cassandra(Cassandra使得我們能夠在一個區域執行寫操作,并用非常低的延遲讓寫入的數據可在所有區域使用。同時還可以幫助我們實現跨區域高可用性)。

  • 第3步 – 最終將SQL數據庫遷移至云中。

從每個國家遷移過程的每一步操作中學習經驗,進行迭代和完善,確保后續工作能取得更好的成績。

第1步 – 將新落地國家重定向至云中,將數據同步回數據中心

Netflix很快將在6個新國家落地。我們決定利用這一機會直接通過云環境運行這些國家的部分計費系統。這意味著面向用戶的數據和應用程序將從云中運行,但依然需要將數據同步回數據中心,這樣數據中心內的批處理應用程序才能繼續運行,不至于影響到業務運轉。這些新落地國家客戶的數據將保存在云中,但批處理任務依然在數據中心內處理。這是我們的第一步。

我們將2個面向用戶的應用程序中的所有API移植到使用Spring Boot和Spring Integration開發的云應用程序中。通過使用Spring Boot可以快速著手創建新應用程序,這個產品內建了開發工作所需的基礎結構和組件,可以讓我們更專注業務邏輯本身。通過使用Spring Integration,只需一次開發碼即可重復使用大部分工作流風格的代碼。借助這些產品對Header以及基于Header的路由技術提供的支持,我們可以在應用程序內部實現Pub-sub模式,將消息放入一個渠道(Channel),并讓每個用戶通過各自獨立的方式使用。在將數據存儲于Cassandra的情況下,現在可以通過任意AWS區域處理這6個新國家會員的API調用。就算某個AWS區域徹底故障,這些國家的計費操作也不會受到影響,而這也是我們首次真正意義上認識到云計算的威力!

我們在AWS多個區域的EC2實例上部署了自己的應用程序,另外為現有的云代理應用程序增加了一個重定向層,以便將新落地國家用戶的計費調用切換至云中新部署的計費API,并讓原有國家用戶的計費調用繼續由數據中心內原有的計費API處理。我們從一個AWS區域建立了到數據中心內現有Oracle數據庫的直接連接,并開發了一個程序,通過SQS將另外3個區域中的Cassandra數據與這個建立了直接連接的區域進行同步。我們還使用SQS隊列和Dead Letter Queues(DLQ)在故障的區域和過程之間移動數據。

在新國家落地通常意味著會員數量的激增。我們也明白,為了確保數據中心不超載,還必須將現有的續訂應用程序從數據中心搬入云中。因此對于通過云服務運行的6個新落地國家,我們編寫了一個爬蟲程序,可以每天一次遍歷Cassandra中的所有客戶,借此找出所有當天需要收費的會員。這種“逐行迭代”的方法目前在這些國家很好用,但我們也清楚,在將其他國家,尤其是美國(目前我們的絕大部分會員都在美國)的數據遷移到云中之后這種方式將會失效。但我們想先行一步試試水有多深。這也是目前這一階段唯一在云中運行的批處理應用程序。

為了能夠在任何一個區域執行寫操作,并將寫操作快速復制到其他區域,我們選擇用Cassandra作為數據存儲。我們定義了一種數據模型,在其中使用customerId作為行,并創建了一系列復合的Cassandra列借此體現數據之間的關系性。下圖展示了這些項之間的關系,以及我們是如何在Cassandra中使用單列族(Single column family)進行體現的。用單列族形式設計這樣的關系使得我們能為相關項提供事務支持。

通過對應用程序的邏輯進行設計,只需要在任何操作開始執行時讀取一次,隨后即可在內存中更新對象,并在操作結束后將其以單列族的形式持久存儲。在操作過程中讀取或寫入Cassandra的操作會被看作一種反模式(Anti-pattern)。我們使用 Astyanax (Netflix自行開發并已開源的Cassandra客戶端)編寫了自定義的ORM,這樣就可以針對Cassandra讀/寫域對象。

我們通過這種方式將服務落地到新的國家,雖然遇到了幾個小問題,但在迅速修復后整個系統運轉很穩定。目前來說一切都挺不錯的!

經過第1步工作后計費系統的體系結構如下圖所示:

第2步 – 遷移所有應用程序,并將原有國家遷移至云中

第1步成功完成后,我們開始考慮在不遷移數據庫的情況下將其他應用遷至云中。大部分業務邏輯位于批處理應用程序中,多年來已經發展得極為成熟,但這也意味著必須深入到每個條件的代碼中并花費大量時間重寫。這些應用程序無法“照原樣”直接搬到云中運行。同時我們也借助這次機會盡量移除了所有不再使用的代碼,將不同功能拆分為多個專用的小應用程序,并為了更好的擴展性重構了現有代碼。這些遺留應用程序被我們設計為會在啟動時讀取磁盤上的配置文件,并使用了其他一些靜態資源,例如從Weblogic隊列讀取消息,由于實例與生俱來的“短暫”本質,這些特征在云環境中都是反模式的。因此為了讓應用程序在云平臺上順利運行,只能重新實現這些模塊。為了通過異步模式將消息穿過隊列移動到不同區域,我們還更改了一些API,并在這些區域建立了到數據中心的安全連接。

云數據庫工程(CDE)團隊為我們的數據需求搭建了多節點Cassandra集群。我們也清楚,在將所有Netflix會員的計費數據遷移到Cassandra之后,以前用來為最早的6個國家的客戶提供續訂服務所用的“全行(Row)式”Cassandra迭代器續訂解決方案將無法很好地伸縮。因此我們使用 Aegisthus 設計了一個系統,可從Cassandra SSTable拉取數據并將其轉換為JSON格式的行,將其暫存在S3 Bucket中。隨后我們寫了一些Pig腳本,借此每天針對大量數據集運行Mapreduce作業,找出需要續訂的客戶清單并向他們收費。我們還寫了Sqoop作業以便從Cassandra和Oracle中拉取數據,并將其以可查詢格式寫入Hive,這樣就可以將這兩套數據集匯總至Hive,實現更快速的排錯。

為了讓DVD服務器能夠連接云環境,我們為DVD設置了負載平衡端點(包含SSL客戶端證書),DVD服務器可以通過云代理對所有調用進行路由,在遷移美國系統之前可以借此將調用重新發回數據中心。美國系統的數據遷移完成后,即可斷開云和數據中心之間的通信鏈路。

為了對這一大規模數據遷移的結果進行驗證,我們編寫了對已遷往云中的數據,以及數據中心內部現有數據進行比較和驗證的對比工具。反復運行該對比工具可找出遷移過程中可能存在的Bug,修復發現的問題,清理數據并再次運行。隨著運行結果愈發整潔,完全沒有出現任何錯誤,這也進一步增強了我們對數據遷移工作的信心。對于針對各國數據進行的遷移工作我們感到十分激動。最開始我們選擇了一個Netflix會員數量比較少的國家,并通過下列步驟將數據遷入云中:

  • 禁用待遷移國家的非GET API(該操作不會影響會員服務,但可能導致計費系統中訂閱更新工作延遲)。

  • 使用Sqoop作業將數據從Oracle轉移至S3和Hive。

  • 使用Pig將其轉換為Cassandra格式。

  • 將該國家所有會員的記錄插入Cassandra。

  • 啟用非GET API,通過云平臺為被遷移國家的用戶提供數據。

在確認一切正常后開始遷移下一個國家。隨后我們開始突擊對所有類似國家一起進行遷移。最后遷移的是美國,因為美國的會員數量最多,并且還提供有DVD訂閱服務。至此所有面向Netflix會員客戶的數據都已通過云環境提供。對我們來說這是一個巨大的里程碑!

經過第2步工作后,我們的體系結構如下圖所示:

第3步 – 再見,數據中心!

至此還有最后(并且最重要)的一件事:數據中心內運行的Oracle數據庫。Oracle中存儲的數據集具有高度的關系性,我們覺得這些數據并不適合以NoSQL的方式進行建模。這種數據不能像以前處理面向客戶的訂閱數據那樣構造為單列族的形式,因此我們評估了Oracle和Aurora RDS這兩種選項。但Oracle作為云數據庫運行的許可成本,以及Aurora依然是Beta測試版這一現狀使得則兩種方式都不適合我們。

在計費團隊忙于執行前兩個步驟時,我們的云數據庫工程團隊正在創建用于將計費數據遷移至EC2上MySQL實例所需的基礎結構。在開始執行第三步操作時,在他們的幫助下數據庫基礎結構部分已經就緒。因為一些應用程序使用了不包含任何ORM的純JDBC,我們還需要將批處理應用程序的代碼基轉換為兼容MySQL的格式。另外我們處理了大量遺留的Pl-sql代碼,并重寫了應用程序中的邏輯,同時盡可能去除了不再使用的代碼。

至此我們的數據庫體系結構已經由部署在某一AWS區域內EC2實例上的MySQL主數據庫組成。我們還搭建了一個從主數據庫復制數據的災難恢復數據庫,如果主數據庫故障,該數據庫將成為新的主數據。另外我們還在在其他AWS區域設置了從數據庫,這些數據庫主要為應用程序提供只讀訪問。

至此我們的計費系統已經全部搬入云中,現在看起來是下面這個樣子:

可想而知,我們從這個大型項目中獲益良多。為了幫助自己調試/排錯并改善開發者的生產力,我們還編寫了幾個工具。我們移除了老舊的以及不再需要的代碼,清理了一些功能并對其他功能進行了力所能及的完善。這個項目得到了Netflix內部很多工程團隊的支持。來自云數據庫工程團隊、訂戶和帳戶工程團隊、支付工程團隊,以及消息工程團隊的成員與我們一起用2周乃至數月的時間幫助我們一起完成這一重大舉措。Netflix文化最棒的地方正在于,所有人心中有著相同的目標:為全球會員提供更精彩的體驗。如果將計費解決方案遷入云中對此有幫助,不管大家屬于哪個團隊,都會為這一目標貢獻自己的力量!

前路…

將計費系統遷入云中后,Netflix流媒體基礎結構已經完全在云中運行。我們可以按需對Netflix的任何服務進行縮放,根據使用模式進行預測式縮放,使用 Spinnaker 進行一鍵點擊部署,并在不同的Netflix應用程序之間實現一致的部署體系結構。計費基礎結構現在可以使用Netflix平臺的所有二進制程序和框架進行監控,并通過云平臺獲得所需的工具支持。目前我們已經可以為全球超過190個國家和地區,8100萬Netflix會員的計費任務提供支持。為了完成所有計費事件,每天我們會生成并處理數TB數據。為了實現全球擴張并順利迎接業務挑戰,我們計劃在未來對會員工作流進行重構。作為全新體系結構的一部分,我們將重新設計現有服務,以便在云環境中以原生的方式實現伸縮。隨著服務在全球發布,我們可以借此機會為新落地的市場研究并改進計費和支付方法,將其與全球合作伙伴以及不同區域的本地支付流程進行集成。我們正在面向未來努力打造功能更豐富,縮放能力更強的體系結構。

 

 

 

 

來自:http://mp.weixin.qq.com/s?__biz=MzI4MjE3MTcwNA==&mid=2664334852&idx=1&sn=84b581c4aa5eb5eea4887a789ef398fa&chksm=f0a42653c7d3af456b0253360d23042634b95678b06893d3cec73747dcb209f03191b598082e&scene=0

 

 本文由用戶 dpcg2771 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!