『壹』 保證分布式系統數據一致性的6種方案
編者按 :本文由「高可用架構後花園」群討論整理而成。
有人的地方,就有江湖
有江湖的地方,就有紛爭
在電商等業務中,系統一般由多個獨立的服務組成,如何解決分布式調用時候數據的一致性?
具體業務場景如下,比如一個業務操作,如果同時調用服務 A、B、C,需要滿足要麼同時成功;要麼同時失敗。A、B、C 可能是多個不同部門開發、部署在不同伺服器上的遠程服務。
在分布式系統來說,如果不想犧牲一致性,CAP 理論告訴我們只能放棄可用性,這顯然不能接受。為了便於討論問題,先簡單介紹下數據一致性的基礎理論。
強一致
弱一致性
最終一致性
在工程實踐上,為了保障系統的可用性,互聯網系統大多將強一致性需求轉換成最終一致性的需求,並通過系統執行冪等性的保證,保證數據的最終一致性。但在電商等場景中,對於數據一致性的解決方法和常見的互聯網系統(如 MySQL 主從同步)又有一定區別,群友的討論分成以下 6 種解決方案。
業務整合方案主要採用將介面整合到本地執行的方法。拿問題場景來說,則可以將服務 A、B、C 整合為一個服務 D 給業務,這個服務 D 再通過轉換為本地事務的方式,比如服務 D 包含本地服務和服務 E,而服務 E 是本地服務 A ~ C 的整合。
優點: 解決(規避)了分布式事務。
缺點: 顯而易見,把本來規劃拆分好的業務,又耦合到了一起,業務職責不清晰,不利於維護。
由於這個方法存在明顯缺點,通常不建議使用。
此方案的核心是將需要分布式處理的任務通過消息日誌的方式來非同步執行。消息日誌可以存儲到本地文本、資料庫或消息隊列,再通過業務規則自動或人工發起重試。人工重試更多的是應用於支付場景,通過對賬系統對事後問題的處理。
消息日誌方案的核心是保證服務介面的冪等性。
考慮到網路通訊失敗、數據丟包等原因,如果介面不能保證冪等性,數據的唯一性將很難保證。
eBay 方式的主要思路如下。
Base:一種 Acid 的替代方案
此方案是 eBay 的架構師 Dan Pritchett 在 2008 年發表給 ACM 的文章,是一篇解釋 BASE 原則,或者說最終一致性的經典文章。文中討論了 BASE 與 ACID 原則在保證數據一致性的基本差異。
如果 ACID 為分區的資料庫提供一致性的選擇,那麼如何實現可用性呢?答案是
BASE (basically available, soft state, eventually consistent)
BASE 的可用性是通過 支持局部故障 而不是系統全局故障來實現的。下面是一個簡單的例子:如果將用戶分區在 5 個資料庫伺服器上,BASE 設計鼓勵類似的處理方式,一個用戶資料庫的故障隻影響這台特定主機那 20% 的用戶。這里不涉及任何魔法,不過它確實可以帶來更高的可感知的系統可用性。
文章中描述了一個最常見的場景,如果產生了一筆交易,需要在交易表增加記錄,同時還要修改用戶表的金額。這兩個表屬於不同的遠程服務,所以就涉及到分布式事務一致性的問題。
文中提出了一個經典的解決方法,將主要修改操作以及更新用戶表的消息 放在一個本地事務 來完成。同時為了避免重復消費用戶表消息帶來的問題,達到多次重試的冪等性, 增加一個更新記錄表 updates_applied 來記錄已經處理過的消息。
系統的執行偽代碼如下
(點擊可全屏縮放圖片)
基於以上方法,在第一階段,通過本地的資料庫的事務保障,增加了 transaction 表及消息隊列 。
在第二階段,分別讀出消息隊列(但不刪除),通過判斷更新記錄表 updates_applied 來檢測相關記錄是否被執行,未被執行的記錄會修改 user 表,然後增加一條操作記錄到 updates_applied,事務執行成功之後再刪除隊列。
通過以上方法,達到了分布式系統的最終一致性。進一步了解 eBay 的方案可以參考文末鏈接。
隨著業務規模不斷地擴大,電商網站一般都要面臨拆分之路。就是將原來一個單體應用拆分成多個不同職責的子系統。比如以前可能將面向用戶、客戶和運營的功能都放在一個系統里,現在拆分為訂單中心、代理商管理、運營系統、報價中心、庫存管理等多個子系統。
拆分首先要面臨的是什麼呢?
最開始的單體應用所有功能都在一起,存儲也在一起。比如運營要取消某個訂單,那直接去更新訂單表狀態,然後更新庫存表就 ok 了。因為是單體應用,庫在一起,這些都可以在一個事務里,由關系資料庫來保證一致性。
但拆分之後就不同了,不同的子系統都有自己的存儲。比如訂單中心就只管理自己的訂單庫,而庫存管理也有自己的庫。那麼運營系統取消訂單的時候就是通過介面調用等方式來調用訂單中心和庫存管理的服務了,而不是直接去操作庫。這就涉及一個『 分布式事務 』的問題。
分布式事務有兩種解決方式
1. 優先使用非同步消息。
上文已經說過,使用非同步消息 Consumer 端需要實現冪等。
冪等有兩種方式, 一種方式是業務邏輯保證冪等 。比如接到支付成功的消息訂單狀態變成支付完成,如果當前狀態是支付完成,則再收到一個支付成功的消息則說明消息重復了,直接作為消息成功處理。
另外一種方式如果業務邏輯無法保證冪等,則要增加一個去重表或者類似的實現 。對於 procer 端在業務資料庫的同實例上放一個消息庫,發消息和業務操作在同一個本地事務里。發消息的時候消息並不立即發出,而是向消息庫插入一條消息記錄,然後在事務提交的時候再非同步將消息發出,發送消息如果成功則將消息庫里的消息刪除,如果遇到消息隊列服務異常或網路問題,消息沒有成功發出那麼消息就留在這里了,會有另外一個服務不斷地將這些消息掃出重新發送。
2. 有的業務不適合非同步消息的方式,事務的各個參與方都需要同步的得到結果。 這種情況的實現方式其實和上面類似,每個參與方的本地業務庫的同實例上面放一個事務記錄庫。
比如 A 同步調用 B,C。A 本地事務成功的時候更新本地事務記錄狀態,B 和 C 同樣。如果有一次 A 調用 B 失敗了,這個失敗可能是 B 真的失敗了,也可能是調用超時,實際 B 成功。則由一個中心服務對比三方的事務記錄表,做一個最終決定。假設現在三方的事務記錄是 A 成功,B 失敗,C 成功。那麼最終決定有兩種方式,根據具體場景:
對 b 場景做一個特殊說明:比如 B 是扣庫存服務,在第一次調用的時候因為某種原因失敗了,但是重試的時候庫存已經變為 0,無法重試成功,這個時候只有回滾 A 和 C 了。
那麼可能有人覺得在業務庫的同實例里放消息庫或事務記錄庫,會對業務侵入,業務還要關心這個庫,是否一個合理的設計?
實際上可以依靠運維的手段來簡化開發的侵入,我們的方法是讓 DBA 在公司所有 MySQL 實例上預初始化這個庫,通過框架層(消息的客戶端或事務 RPC 框架)透明的在背後操作這個庫,業務開發人員只需要關心自己的業務邏輯,不需要直接訪問這個庫。
總結起來,其實兩種方式的根本原理是類似的,也就是 將分布式事務轉換為多個本地事務,然後依靠重試等方式達到最終一致性 。
交易創建的一般性流程
我們把交易創建流程抽象出一系列可擴展的功能點,每個功能點都可以有多個實現(具體的實現之間有組合/互斥關系)。把各個功能點按照一定流程串起來,就完成了交易創建的過程。
面臨的問題
每個功能點的實現都可能會依賴外部服務。那麼如何保證各個服務之間的數據是一致的呢?比如鎖定優惠券服務調用超時了,不能確定到底有沒有鎖券成功,該如何處理?再比如鎖券成功了,但是扣減庫存失敗了,該如何處理?
方案選型
服務依賴過多,會帶來管理復雜性增加和穩定性風險增大的問題。試想如果我們強依賴 10 個服務,9 個都執行成功了,最後一個執行失敗了,那麼是不是前面 9 個都要回滾掉?這個成本還是非常高的。
所以在拆分大的流程為多個小的本地事務的前提下,對於非實時、非強一致性的關聯業務寫入,在本地事務執行成功後,我們選擇發消息通知、關聯事務非同步化執行的方案。
消息通知往往不能保證 100% 成功;且消息通知後,接收方業務是否能執行成功還是未知數。前者問題可以通過重試解決;後者可以選用事務消息來保證。
所以目前只剩下需要實時同步做、有強一致性要求的業務場景了。在交易創建過程中,鎖券和扣減庫存是這樣的兩個典型場景。
要保證多個系統間數據一致,乍一看,必須要引入分布式事務框架才能解決。但引入非常重的類似二階段提交分布式事務框架會帶來復雜性的急劇上升;在電商領域,絕對的強一致是過於理想化的,我們可以選擇准實時的最終一致性。
我們在交易創建流程中, 首先創建一個不可見訂單 ,然後在同步調用鎖券和扣減庫存時,針對調用異常(失敗或者超時),發出廢單消息到MQ。如果消息發送失敗,本地會做時間階梯式的非同步重試;優惠券系統和庫存系統收到消息後,會進行判斷是否需要做業務回滾,這樣就准實時地保證了多個本地事務的最終一致性。
業界常用的還有支付寶的一種 xts 方案,由支付寶在 2PC 的基礎上改進而來。主要思路如下,大部分信息引用自官方網站。
分布式事務服務簡介
分布式事務服務 (Distributed Transaction Service, DTS) 是一個分布式事務框架,用來保障在大規模分布式環境下事務的最終一致性。DTS 從架構上分為 xts-client 和 xts-server 兩部分,前者是一個嵌入客戶端應用的 JAR 包,主要負責事務數據的寫入和處理;後者是一個獨立的系統,主要負責異常事務的恢復。
核心特性
傳統關系型資料庫的事務模型必須遵守 ACID 原則。在單資料庫模式下,ACID 模型能有效保障數據的完整性,但是在大規模分布式環境下,一個業務往往會跨越多個資料庫,如何保證這多個資料庫之間的數據一致性,需要其他行之有效的策略。在 JavaEE 規范中使用 2PC (2 Phase Commit, 兩階段提交) 來處理跨 DB 環境下的事務問題,但是 2PC 是反可伸縮模式,也就是說,在事務處理過程中,參與者需要一直持有資源直到整個分布式事務結束。這樣,當業務規模達到千萬級以上時,2PC 的局限性就越來越明顯,系統可伸縮性會變得很差。基於此,我們採用 BASE 的思想實現了一套類似 2PC 的分布式事務方案,這就是 DTS。DTS在充分保障分布式環境下高可用性、高可靠性的同時兼顧數據一致性的要求,其最大的特點是保證數據最終一致 (Eventually consistent)。
簡單的說,DTS 框架有如下特性:
以下是分布式事務框架的流程圖
實現
與 2PC 協議比較
1. 電商業務
公司的支付部門,通過接入其它第三方支付系統來提供支付服務給業務部門,支付服務是一個基於 Dubbo 的 RPC 服務。
對於業務部門來說,電商部門的訂單支付,需要調用
從業務規則上需要同時保證業務數據的實時性和一致性,也就是支付成功必須加積分。
我們採用的方式是同步調用,首先處理本地事務業務。考慮到積分業務比較單一且業務影響低於支付,由積分平台提供增加與回撤介面。
具體的流程是先調用積分平台增加用戶積分,再調用支付平台進行支付處理,如果處理失敗,catch 方法調用積分平台的回撤方法,將本次處理的積分訂單回撤。
(點擊圖片可以全屏縮放)
2. 用戶信息變更
分布式服務對衍生的配套系統要求比較多,特別是我們基於消息、日誌的最終一致性方案,需要考慮消息的積壓、消費情況、監控、報警等。
In partitioned databases, trading some consistency for availability can lead to dramatic improvements in scalability.
英文版 : http://queue.acm.org/detail.cfm?id=1394128
中文版: http://article.yeeyan.org/view/167444/125572
感謝李玉福、余昭輝、蘑菇街七公提供方案,其他多位群成員對本文內容亦有貢獻。
本文編輯李玉福、Tim Yang,轉載請註明來自@高可用架構
『貳』 集中式數據處理和分布式數據處理的優缺點
集中式數據處理優點:
1、部署結構簡單。
2、數據容易備份,只需要把中央計算機上的數據備份即可。
3、不易感染病毒,只要對中央計算機做好保護,終端一般不需要外接設備,感染病毒的幾率很低。
4、總費用較低,中央計算機的功能非常強大,終端只需要簡單、便宜的設備。
缺點:
1、中央計算機需要執行所有的運算,當終端很多時,會導致響應速度變慢。
2、如果終端用戶有不同的需要,要對每個用戶的程序和資源做單獨的配置,在集中式系統上做起來比較困難,而且效率不高。
分布式數據處理優點:
1、分布式網路中的每台機器都能存儲和處理數據,降低了對機器性能的要求,所以不必購買昂貴的高性能機器,這大大降低了硬體投資成本。
2、擴展性極佳。在當前系統存儲或計算能力不足時,可以簡單地通過增加廉價PC機的方式來增加系統的處理和存儲能力。
3、處理能力極強。龐大的計算任務可以在合理分割後由分布式網路中的機器並行地處理
缺點
1、計算程序全負荷運行時仍會對計算機的各個部件造成一定壓力。
2、對項目方來說,參加分布式計算的志願者不是項目方自己的人員,不是全體可信任,因此必須引入一定的冗餘計算機制,才能防止計算錯誤、惡意作弊等。
(2)分布式數據處理怎樣實現其准確性擴展閱讀
分布式計算為信息不只分布在一個軟體或計算機上,而是分布於多個軟體上,可以用多台或一台計算機同時運行若干個軟體,通過網路實現信息的共享。與其他演算法相比,分布式演算法有明顯的優勢:
1、共享資源更加方便。
2、能夠實現計算負載的平衡,用多台計算機同時處理任務。
3、可以根據實際需要合理選擇適當的計算機運行該程序。計算機分布式計算的靈魂是平衡負載和共享資源。分布式計算具有高效、快捷、准確的優勢
『叄』 什麼是分布式資料庫系統分布式資料庫系統有哪些特點
分布式資料庫是一個邏輯資料庫,它的物理資料庫在地理位置上分布在多個資料庫管理系統的計算機網路中,這些資料庫系統構成了分布式的資料庫管理系統。在分布式資料庫管理系統中,每台計算機上的用戶在訪問資料庫時並不感到他使用的數據在物理上不存儲在自己的計算機中,而是由分布式資料庫系統由網路從其它機器中傳輸過來。因此,對每一用戶來說,看到的都是一個統一的概念模式。分布式資料庫系統的主要特點是:(1)具有較高的可靠性,當系統中一台機器發生故障時、不會導致整個系統的破壞。當故障排除後,分布式資料庫系統可將故障期間的資料庫加以恢復修改。(2)分散了工作負荷,使大量的處理均勻分擔。(3)便於實現系統的擴充。分布式資料庫系統是計算機通訊和資料庫技術相結合的產物,是非常有代表性的資料庫技術發展方向之一。
『肆』 在設計一個可靠好的分布式資料庫時,應該考慮哪些問題
在設計分布式資料庫時,應特別考慮如下幾個方面的問題:
1. 數據保存 (存儲分段/復制,橫向/縱向表分區);
2. 目錄管理(catalog management): 命名,數據獨立性
3. 查詢處理(基於代價的調優, 半合並)4. 數據更新(同步/非同步)
『伍』 分布式存儲中,怎樣使用paxos演算法保證數據的一致性
在分布式系統中,我們經常遇到多數據副本保持一致的問題,在我們所能找到的資料中該問題講的很籠統,模模糊糊的,把多個問題或分類糅合在一起,難以理解。在思考和翻閱資料後,通俗地把一致性的問題可分解為2個問題:
1、任何一次修改保證數據一致性。
2、多次數據修改的一致性。
在弱一致性的演算法,不要求每次修改的內容在修改後多副本的內容是一致的,對問題1的解決比較寬松,更多解決問題2,該類演算法追求每次修改的高度並發性,減少多副本之間修改的關聯性,以獲得更好的並發性能。例如最終一致性,無所謂每次用戶修改後的多副本的一致性及格過,只要求在單調的時間方向上,數據最終保持一致,如此獲得了修改極大的並發性能。
在強一致性的演算法中,強調單次修改後結果的一致,需要保證了對問題1和問題2要求的實現,犧牲了並發性能。本文是討論對解決問題1實現演算法,這些演算法往往在強一致性要求的應用中使用。
解決問題1的方法,通常有兩階段提交演算法、採用分布式鎖服務和採用樂觀鎖原理實現的同步方式,下面分別介紹這幾種演算法的實現原理。
兩階段提交演算法
在兩階段提交協議中,系統一般包含兩類機器(或節點):一類為協調者(coordinator),通常一個系統中只有一個;另一類為事務參與者(participants,cohorts或workers),一般包含多個,在數據存儲系統中可以理解為數據副本的個數。兩階段提交協議由兩個階段組成,在正常的執行下,這兩個階段的執行過程如下所述:
階段1:請求階段(commit-request phase,或稱表決階段,voting phase)。
在請求階段,協調者將通知事務參與者准備提交或取消事務,然後進入表決過程。在表決過程中,參與者將告知協調者自己的決策:同意(事務參與者本地作業執行成功)或取消(本地作業執行故障)。
階段2:提交階段(commit phase)。
在該階段,協調者將基於第一個階段的投票結果進行決策:提交或取消。當且僅當所有的參與者同意提交事務協調者才通知所有的參與者提交事務,否則協調者將通知所有的參與者取消事務。參與者在接收到協調者發來的消息後將執行響應的操作。
舉個例子:A組織B、C和D三個人去爬長城:如果所有人都同意去爬長城,那麼活動將舉行;如果有一人不同意去爬長城,那麼活動將取消。用2PC演算法解決該問題的過程如下:
首先A將成為該活動的協調者,B、C和D將成為該活動的參與者。
階段1:A發郵件給B、C和D,提出下周三去爬山,問是否同意。那麼此時A需要等待B、C和D的郵件。B、C和D分別查看自己的日程安排表。B、C發現自己在當日沒有活動安排,則發郵件告訴A它們同意下周三去爬長城。由於某種原因,D白天沒有查看郵件。那麼此時A、B和C均需要等待。到晚上的時候,D發現了A的郵件,然後查看日程安排,發現周三當天已經有別的安排,那麼D回復A說活動取消吧。
階段2:此時A收到了所有活動參與者的郵件,並且A發現D下周三不能去爬山。那麼A將發郵件通知B、C和D,下周三爬長城活動取消。此時B、C回復A「太可惜了」,D回復A「不好意思」。至此該事務終止。
兩階段提交演算法在分布式系統結合,可實現單用戶對文件(對象)多個副本的修改,多副本數據的同步。其結合的原理如下:
1、客戶端(協調者)向所有的數據副本的存儲主機(參與者)發送:修改具體的文件名、偏移量、數據和長度信息,請求修改數據,該消息是1階段的請求消息。
2、存儲主機接收到請求後,備份修改前的數據以備回滾,修改文件數據後,向客戶端回應修改成功的消息。 如果存儲主機由於某些原因(磁碟損壞、空間不足等)不能修改數據,回應修改失敗的消息。
3、客戶端接收發送出去的每一個消息回應,如果存儲主機全部回應都修改成功,向每存儲主機發送確認修改的提交消息;如果存在存儲主機回應修改失敗,或者超時未回應,客戶端向所有存儲主機發送取消修改的提交消息。該消息是2階段的提交消息。
4、存儲主機接收到客戶端的提交消息,如果是確認修改,則直接回應該提交OK消息;如果是取消修改,則將修改數據還原為修改前,然後回應取消修改OK的消息。
5、 客戶端接收全部存儲主機的回應,整個操作成功。
在該過程中可能存在通信失敗,例如網路中斷、主機宕機等諸多的原因,對於未在演算法中定義的其它異常,都認為是提交失敗,都需要回滾,這是該演算法基於確定的通信回復實現的,在參與者的確定回復(無論是回復失敗還是回復成功)之上執行邏輯處理,符合確定性的條件當然能夠獲得確定性的結果哲學原理。
分布式鎖服務
分布式鎖是對數據被外界修改持保守態度,在整個數據處理過程中將數據處於鎖定狀態,在用戶修改數據的同時,其它用戶不允許修改。
採用分布式鎖服務實現數據一致性,是在操作目標之前先獲取操作許可,然後再執行操作,如果其他用戶同時嘗試操作該目標將被阻止,直到前一個用戶釋放許可後,其他用戶才能夠操作目標。分析這個過程,如果只有一個用戶操作目標,沒有多個用戶並發沖突,也申請了操作許可,造成了由於申請操作許可所帶來的資源使用消耗,浪費網路通信和增加了延時。
採用分布式鎖實現多副本內容修改的一致性問題, 選擇控制內容顆粒度實現申請鎖服務。例如我們要保證一個文件的多個副本修改一致, 可以對整個文件修改設置一把鎖,修改時申請鎖,修改這個文件的多個副本,確保多個副本修改的一致,修改完成後釋放鎖;也可以對文件分段,或者是文件中的單個位元組設置鎖, 實現更細顆粒度的鎖操作,減少沖突。
常用的鎖實現演算法有Lamport bakery algorithm (俗稱麵包店演算法), 還有Paxos演算法。下面對其原理做簡單概述。
Lamport麵包店演算法
是解決多個線程並發訪問一個共享的單用戶資源的互斥問題的演算法。 由Leslie Lamport(英語:Leslie Lamport)發明。
Lamport把這個並發控制演算法可以非常直觀地類比為顧客去麵包店采購。麵包店只能接待一位顧客的采購。已知有n位顧客要進入麵包店采購,安排他們按照次序在前台登記一個簽到號碼。該簽到號碼逐次加1。根據簽到號碼的由小到大的順序依次入店購貨。完成購買的顧客在前台把其簽到號碼歸0. 如果完成購買的顧客要再次進店購買,就必須重新排隊。
這個類比中的顧客就相當於線程,而入店購貨就是進入臨界區獨占訪問該共享資源。由於計算機實現的特點,存在兩個線程獲得相同的簽到號碼的情況,這是因為兩個線程幾乎同時申請排隊的簽到號碼,讀取已經發出去的簽到號碼情況,這兩個線程讀到的數據是完全一樣的,然後各自在讀到的數據上找到最大值,再加1作為自己的排隊簽到號碼。為此,該演算法規定如果兩個線程的排隊簽到號碼相等,則線程id號較小的具有優先權。
把該演算法原理與分布式系統相結合,即可實現分步鎖。
Paxos演算法
該演算法比較熱門,參見WIKI,http://zh.wikipedia.org/wiki/Paxos%E7%AE%97%E6%B3%95
Paxos演算法解決的問題是一個分布式系統如何就某個值(決議)達成一致。一個典型的場景是,在一個分布式資料庫系統中,如果各節點的初始狀態一致,每個節點都執行相同的操作序列,那麼他們最後能得到一個一致的狀態。為保證每個節點執行相同的命令序列,需要在每一條指令上執行一個「一致性演算法」以保證每個節點看到的指令一致。一個通用的一致性演算法可以應用在許多場景中,是分布式計算中的重要問題。節點通信存在兩種模型:共享內存(Shared memory)和消息傳遞(Messages passing)。Paxos演算法就是一種基於消息傳遞模型的一致性演算法。BigTable使用一個分布式數據鎖服務Chubby,而Chubby使用Paxos演算法來保證備份的一致性。
採用樂觀鎖原理實現的同步
我們舉個例子說明該演算法的實現原理。如一個金融系統,當某個操作員讀取用戶的數據,並在讀出的用戶數據的基礎上進行修改時(如更改用戶帳戶余額),如果採用前面的分布式鎖服務機制,也就意味著整個操作過程中(從操作員讀出數據、開始修改直至提交修改結果的全過程,甚至還包括操作員中途去煮咖啡的時間),資料庫記錄始終處於加鎖狀態,可以想見,如果面對幾百上千個並發,這樣的情況將導致怎樣的後果。
樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基於數據版本( Version)記錄機制實現。何謂數據版本?即為數據增加一個版本標識,在基於資料庫表的版本解決方案中,一般是通過為資料庫表增加一個 「version」 欄位來實現。讀取出數據時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交數據的版本數據與資料庫表對應記錄的當前版本信息進行比對,如果提交的數據版本號大於資料庫表當前版本號,則予以更新,否則認為是過期數據。
對於上面修改用戶帳戶信息的例子而言,假設資料庫中帳戶信息表中有一個 version 欄位,當前值為 1 ;而當前帳戶余額欄位( balance )為 $100 。
操作員 A 此時將其讀出(version=1 ),並從其帳戶余額中扣除 $50($100-$50 )。
在操作員 A 操作的過程中,操作員B也讀入此用戶信息( version=1 ),並從其帳戶余額中扣除 $20 ( $100-$20 )。
操作員 A 完成了修改工作,將數據版本號加一( version=2 ),連同帳戶扣除後余額( balance=$50 ),提交至資料庫更新,此時由於提交數據版本大於資料庫記錄當前版本,數據被更新,資料庫記錄 version 更新為 2 。
操作員 B 完成了操作,也將版本號加一( version=2 )試圖向資料庫提交數據( balance=$80 ),但此時比對資料庫記錄版本時發現,操作員 B 提交的數據版本號為 2 ,資料庫記錄當前版本也為 2 ,不滿足 「 提交版本必須大於記錄當前版本才能執行更新 「 的樂觀鎖策略,因此,操作員 B 的提交被駁回。這樣,就避免了操作員 B 用基於 version=1 的舊數據修改的結果覆蓋操作員A 的操作結果的可能。
樂觀鎖機制與分布式系統相結合上, 我整理了偽代碼如下:
obj 操作的目標
vlaue 修改的值
atom_update_ver 每個目標上的版本,每次修改該值遞增
set( obj, value)
{
//從每個節點上取出修改前的對象版本
get original_ver = obj.atom_update_ver from each node;
//將值賦到每個節點的obj目標
set obj = value from each node;
//條件修改每個節點的obj版本,目標版本加一
//比較和修改操作是原子操作
result = (set obj.atom_update_ver = original_ver + 1
where original_ver + 1 > obj.atom_update_ver
for each node);
if(result == ok)
return set_ok;
else
return set(obj, value);//不成功遞歸修改
該演算法未考慮節點下線、失效等問題,在後續我將分析採用樂觀鎖原理實現一致性演算法,解決問題2、節點失效、通信失敗等問題。
『陸』 如何解決分布式系統數據事務一致性問題
文探討了在分布式系統中,如何基於業務方面的考量、將RESTful與MQ(消息中間件)結合、解決事務完整性/數據一致性問題的架構設計。
一、面向業務考量的最終一致性方案考慮
這里先舉兩個例子。
1、支付寶的「WS Transaction標准」嘗試:
支付寶在他們的分布式系統中為解決事務完整性的問題,曾經嘗試過WS Transaction標准,但是經過實際做測試,最後發現成本實在是太高了。完成一個事務,為確保事務完整性,20多條的消息的交互,其中只有1條是業務消息,其他都是系統之間的協議消息。這就會導致客戶端響應太慢,客戶無法承受這樣的性能。
2、Ebay架構師的最終一致性方案:
來自Ebay的架構師根據他們的最佳實踐給出過解決方案。就是關於數據一致性的,比如他們的分布式存儲如何保持數據一致性。其中探討了「實時一致」與「嚴格事務」之間的悖論,他們採用了局部實時一致、全局最終一致的解決方案。在這里就需要從業務上辨別哪些操作是可以放寬的(允許不在一個事務中),哪些操作必須是原子性的。現在Ebay的整個架構就是基於「最終一致性」的,支付寶也從中受到啟發,沿用該設計思路解決了「客戶端迅速響應」和「服務端數據一致」的矛盾。
故考慮系統架構設計的時候,不僅僅考慮技術,也把業務因素考慮進來,面向業務考量進行系統設計,會讓我們在技術上做出更合理的抉擇。基於業務考慮,有利於得出事務的優先順序別,也有利於作出架構設計上的最佳取捨。通常來說銀行、證券系統的事務完整性(或者說數據一致性)具有絕對優先順序,也就要求絕對嚴格的實時保證。而通訊系統在事務完整性(或者說數據一致性上)的優先順序別上甚至沒有支付寶和Ebay高,這兩者都有復雜的帳務交易。如果他們也認為局部實時一致、全局最終一致就能夠滿足業務的要求,那麼自然在通訊系統中也有其可行性。
二、Restful與MQ技術適用場景分析
一般而言Restful技術架構為對客戶端開放的一組資源服務。在分布式系統中既有客戶端與伺服器之間的交互,又有伺服器與伺服器之間的交互。比如說XCAP協議就是標準的Restful風格的介面,提供客戶端遠程操作XML文檔的服務,而「運營管理系統」調用其他業務系統介面,用以管理用戶可被分配的服務以及許可權等,則是伺服器之間的信息交互。前者當然適合Restful風格的技術介面,後者個人更傾向於非同步的、基於消息的通信方式。因為客戶端與伺服器通常是跨越互聯網的,而伺服器與伺服器之間可能位於一個區域網內,甚至可能被安放在同一個機房。
我們知道Restful風格的技術架構通常是通過JSON或者XML等進行信息的傳遞,總之都是通過「字元串格式」的封裝進行信息傳遞。通過字元格式交互信息在使用上帶來簡便的同時,因為封裝、解析、轉換等過程使其在性能自然要付出一些代價,如果是伺服器之間在更底層同類協議之間的數據交互性能就要高的多。這里順便提到信息交互在不同場景下的性能順序,按照從快到慢排序:
1、同一進程之間的信息交互;
2、同一機器兩個進程之間的信息交互;
3、兩個分布機器之間的信息交互。
因為HTTP是在TCP/IP協議之上的包裝,WebService是在HTTP協議之上的包裝,根據越低層協議之間的信息交互越高效的特徵,從協議級由快到慢排序:
1、基於TCP/IP協議的信息交互;
2、基於HTTP協議的信息交互;
3、基於WebService協議的信息交互。
另外,因為「運營管理系統」與其他系統之間是直接交互的,比如運營要給某個用戶開通某些特定服務,那就要分別調用提供這幾個服務的業務系統的「細粒度」介面。一旦增加新的服務,也勢必影響到運營管理系統的修改。我們說在分布式系統中有個原則,盡可能設計「粗粒度」介面,以減少系統之間的網路交互。如果在運營管理系統與其他業務系統之間由「消息中間件」來進行信息交互,那麼:
1、運營管理系統可以設計面向服務的「粗粒度」介面,開通幾個服務只需要把幾種類型的數據封裝在一起,一次性傳遞給MQ。增加服務也只不過增加一種數據類型而已;
2、MQ可以保證消息最終一定會被接收、處理。因為MQ可以實現基於「訂閱-通知」的Event-Driven機制,業務系統只要在MQ中注冊自己,就可以實時收到來自MQ的消息。即使出現系統或者網路異常,消息也會被MQ中間件持久化,一旦業務系統恢復,消息馬上會被發往業務系統,這顯然比目前採用的每隔一段時間掃描一次資料庫要高效的多。
三、MQ與最終一致性
MQ消息隊列技術是分布式應用間交換信息的一種技術。消息隊列可駐留在內存或磁碟上,隊列存儲消息直到它們被應用程序讀走。通過消息隊列,應用程序可獨立地執行——它們不需要知道彼此的位置、或在繼續執行前不需要等待接收程序接收此消息。它為構造非同步方式實現的分布式應用提供了松耦合方法,在應用中以執行多種功能,比如要求服務、交換信息或非同步處理等。
在分布式系統中,尤其是不同語言的分布式系統中,如果沒有消息中間件完成信息交換,應用開發者為了高效傳輸數據,就要編寫相應語言的應用程序來發送和接收信息,且交換信息沒有標准方法,每個應用必須進行特定的編程從而和多平台、不同環境下的一個或多個應用通信。
假如系統可以採用數據「局部實時一致、全局最終一致」的方案,就可以選擇不需要支持事務的MQ中間件,因為其可以保證:即使在系統異常、網路異常等特殊情況下,消息也會被持久化,當系統恢復,消息馬上會被處理,也即最終一定會被接受處理,也就是最終一致。而不需要支持事務的MQ性能及吞吐率都會很高。
總之,個人傾向於用 Restful對客戶端提供服務,伺服器之間引入MQ服務,建立非同步的、基於消息的信息交互方式,並基於數據局部實時一致、全局最終一致的原則,來解決事務問題。
『柒』 如何確保數據,信息的准確性,完整性,可靠性,及時性,安全性和保密性
數據完整性(Data Integrity)是
指數據的精確性(Accuracy) 和可靠性(Reliability)。它是應防止資料庫中存在不符合語義規定的數據和防止因錯誤信息的輸入輸出造成無效操作或錯誤信息而提出的。數據完整性分為四類:實體完整性(Entity Integrity)、域完整
性(Domain Integrity)、參照完整性(Referential Integrity)、用戶定義的完整性(User-definedIntegrity)。
保證數據的完整性:
用約束而非商務規則強制數據完整性
如果你按照商務規則來處理需求,那麼你應當檢查商務層次/用戶界面:如果商務規則以後發生變化,那麼只需要進行更新即可。
假如需求源於維護數據完整性的需要,那麼在資料庫層面上需要施加限制條件。
如果你在數據層確實採用了約束,你要保證有辦法把更新不能通過約束檢查的原因採用用戶理解的語言通知用戶界面。除非你的欄位命名很冗長,否則欄位名本身還不夠。 — Lamont Adams
只要有可能,請採用資料庫系統實現數據的完整性。這不但包括通過標准化實現的完整性而且還包括數據的功能性。在寫數據的時候還可以增加觸發器來保證數據的正確性。不要依賴於商務層保證數據完整性;它不能保證表之間(外鍵)的完整性所以不能強加於其他完整性規則之上。
— Peter Ritchie
2. 分布式數據系統
對分布式系統而言,在你決定是否在各個站點復制所有數據還是把數據保存在一個地方之前應該估計一下未來5 年或者10 年的數據量。當你把數據傳送到其他站點的時候,最好在資料庫欄位中設置一些標記。在目的站點收到你的數據之後更新你的標記。為了進行這種數據傳輸,請寫下你自己的批處理或者調度程序以特定時間間隔運行而不要讓用戶在每天的工作後傳輸數據。本地拷貝你的維護數據,比如計算常數和利息率等,設置版本號保證數據在每個站點都完全一致。
— Suhair TechRepublic
3. 強制指示完整性
沒有好辦法能在有害數據進入資料庫之後消除它,所以你應該在它進入資料庫之前將其剔除。激活資料庫系統的指示完整性特性。這樣可以保持數據的清潔而能迫使開發人員投入更多的時間處理錯誤條件。
— kol
4. 關系
如果兩個實體之間存在多對一關系,而且還有可能轉化為多對多關系,那麼你最好一開始就設置成多對多關系。從現有的多對一關系轉變為多對多關系比一開始就是多對多關系要難得多。
— CS Data Architect
5. 採用視圖
為了在你的資料庫和你的應用程序代碼之間提供另一層抽象,你可以為你的應用程序建立專門的視圖而不必非要應用程序直接訪問數據表。這樣做還等於在處理資料庫變更時給你提供了更多的自由。
— Gay Howe
6. 給數據保有和恢復制定計劃
考慮數據保有策略並包含在設計過程中,預先設計你的數據恢復過程。採用可以發布給用戶/開發人員的數據字典實現方便的數據識別同時保證對數據源文檔化。編寫在線更新來「更新查詢」供以後萬一數據丟失可以重新處理更新。
— kol
7. 用存儲過程讓系統做重活
解決了許多麻煩來產生一個具有高度完整性的資料庫解決方案之後,我所在的團隊決定封裝一些關聯表的功能組,提供一整套常規的存儲過程來訪問各組以便加快速度和簡化客戶程序代碼的開發。在此期間,我們發現3GL 編碼器設置了所有可能的錯誤條件,比如以下所示:
SELECT Cnt = COUNT (*)
FROM [<Table>]
WHERE [<primary key column>] = <new value>
IF Cnt = 0
BEGIN
INSERT INTO [<Table>]
( [< primary key column>] )
VALUES ( <New value> )
ELSE
BEGIN
<indicate plication error>
而一個非3GL 編碼器是這樣做的:
INSERT INTO [<Table>]
( [< primary key column>] )
VALUES
( <New value> )
IF @@ERROR = 2627 -- Literal error code for Primary Key Constraint
BEGIN
<indicate plication error>
第2 個程序簡單多了,而且事實上,利用了我們給資料庫的功能。雖然我個人不喜歡使用嵌入文字(2627)。但是那樣可以很方便地用一點預先處理來代替。資料庫不只是一個存放數據的地方,它也是簡化編碼之地。
— a-smith
8. 使用查找
控制數據完整性的最佳方式就是限制用戶的選擇。只要有可能都應該提供給用戶一個清晰的價值列表供其選擇。這樣將減少鍵入代碼的錯誤和誤解同時提供數據的一致性。某些公共數據特別適合查找:國家代碼、狀態代碼等
『捌』 Hadoop與分布式數據處理 Spark VS Hadoop有哪些異同點
Spark是一個開源的通用並行分布式計算框架,由加州大學伯克利分校的AMP實驗室開發,支持內存計算、多迭代批量處理、即席查詢、流處理和圖計算等多
種範式。Spark內存計算框架適合各種迭代演算法和互動式數據分析,能夠提升大數據處理的實時性和准確性,現已逐漸獲得很多企業的支持,如阿里巴巴、百
度、網易、英特爾等公司。
針對以下幾個問題來深入的學習
1、 Spark VSHadoop有哪些異同點?
Hadoop:分布式批處理計算,強調批處理,常用於數據挖掘、分析
Spark:是一個基於內存計算的開源的集群計算系統,目的是讓數據分析更加快速, Spark 是一種與 Hadoop
相似的開源集群計算環境,但是兩者之間還存在一些不同之處,這些有用的不同之處使 Spark 在某些工作負載方面表現得更加優越,換句話說,Spark
啟用了內存分布數據集,除了能夠提供互動式查詢外,它還可以優化迭代工作負載。
Spark 是在 Scala 語言中實現的,它將 Scala 用作其應用程序框架。與 Hadoop 不同,Spark 和 Scala 能夠緊密集成,其中的 Scala 可以像操作本地集合對象一樣輕松地操作分布式數據集。
盡管創建 Spark 是為了支持分布式數據集上的迭代作業,但是實際上它是對 Hadoop 的補充,可以在 Hadoop
文件系統中並行運行。通過名為Mesos的第三方集群框架可以支持此行為。Spark 由加州大學伯克利分校 AMP 實驗室
(Algorithms,Machines,and People Lab) 開發,可用來構建大型的、低延遲的數據分析應用程序。
雖然 Spark 與 Hadoop 有相似之處,但它提供了具有有用差異的一個新的集群計算框架。首先,Spark
是為集群計算中的特定類型的工作負載而設計,即那些在並行操作之間重用工作數據集(比如機器學習演算法)的工作負載。為了優化這些類型的工作負
載,Spark 引進了內存集群計算的概念,可在內存集群計算中將數據集緩存在內存中,以縮短訪問延遲.
在大數據處理方面相信大家對hadoop已經耳熟能詳,基於GoogleMap/Rece來實現的Hadoop為開發者提供了map、rece原
語,使並行批處理程序變得非常地簡單和優美。Spark提供的數據集操作類型有很多種,不像Hadoop只提供了Map和Rece兩種操作。比如
map,filter, flatMap,sample, groupByKey, receByKey, union,join,
cogroup,mapValues,
sort,partionBy等多種操作類型,他們把這些操作稱為Transformations。同時還提供Count,collect,
rece, lookup,
save等多種actions。這些多種多樣的數據集操作類型,給上層應用者提供了方便。各個處理節點之間的通信模型不再像Hadoop那樣就是唯一的
Data Shuffle一種模式。用戶可以命名,物化,控制中間結果的分區等。可以說編程模型比Hadoop更靈活.
2、Spark在容錯性方面是否比其他工具更有優越性?
從Spark的論文《Resilient Distributed Datasets:
AFault-TolerantAbstraction for In-Memory Cluster
Computing》中沒看出容錯性做的有多好。倒是提到了分布式數據集計算,做checkpoint的兩種方式,一個是checkpoint
data,一個是loggingthe
updates。貌似Spark採用了後者。但是文中後來又提到,雖然後者看似節省存儲空間。但是由於數據處理模型是類似DAG的操作過程,由於圖中的某
個節點出錯,由於lineage
chains的依賴復雜性,可能會引起全部計算節點的重新計算,這樣成本也不低。他們後來說,是存數據,還是存更新日誌,做checkpoint還是由用
戶說了算吧。相當於什麼都沒說,又把這個皮球踢給了用戶。所以我看就是由用戶根據業務類型,衡量是存儲數據IO和磁碟空間的代價和重新計算的代價,選擇代
價較小的一種策略。取代給中間結果進行持久化或建立檢查點,Spark會記住產生某些數據集的操作序列。因此,當一個節點出現故障時,Spark會根據存
儲信息重新構造數據集。他們認為這樣也不錯,因為其他節點將會幫助重建。
3、Spark對於數據處理能力和效率有哪些特色?
Spark提供了高的性能和大數據處理能力,使得用戶可以快速得到反饋體驗更好。另一類應用是做數據挖掘,因為Spark充分利用內存進行緩存,利用
DAG消除不必要的步驟,所以比較合適做迭代式的運算。而有相當一部分機器學習演算法是通過多次迭代收斂的演算法,所以適合用Spark來實現。我們把一些常
用的演算法並行化用Spark實現,可以從R語言中方便地調用,降低了用戶進行數據挖掘的學習成本。
Spark配有一個流數據處理模型,與Twitter的
Storm框架相比,Spark採用了一種有趣而且獨特的辦法。Storm基本上是像是放入獨立事務的管道,在其中事務會得到分布式的處理。相
反,Spark採用一個模型收集事務,然後在短時間內(我們假設是5秒)以批處理的方式處理事件。所收集的數據成為他們自己的RDD,然後使用Spark
應用程序中常用的一組進行處理。作者聲稱這種模式是在緩慢節點和故障情況下會更加穩健,而且5秒的時間間隔通常對於大多數應用已經足夠快了。這種方法也很
好地統一了流式處理與非流式處理部分。
總結
這幾天在看Hadoop權威指南、hbase權威指南、hive權威指南、大規模分布式存儲系統、zoopkeeper、大數據互聯網大規模數據挖掘與分布式處理等書同時補充,能靜下心來好好的完整的看完一本書,是相當不錯的。
『玖』 做數據分析如何保障數據的准確性
從業多年,在數據准確性上摔過不少跟斗,總結了一些切實有效的方法,能夠幫你盡可能的規避錯誤,確保數據的准確性,分享給大家
對數據上游的管理雖然看上去,數據分析師是掌握數據資源的人,但從數據的生產流程來看,數據分析師其實位於數據的下游,數據需要至少先經過採集環節、清洗環節、存儲環節才能被數據分析師拿到,甚至有的體量特別大的數據,他的調取和處理環節也不能被數據分析師控制。所以,想要最終做出的數據不出錯,那就要先確保我們的數據上游是准確的。
雖然數據上游一般是由其他業務或技術人員負責,但數據分析師也可以通過提需求或生產過程參與的方式,對數據上游進行管理:
設立數據「安檢站」「大包小包過機安檢」只要你坐過北京的地鐵,相信這句話一定耳熟能詳,為了確保所有旅客不把易燃易爆等危險品帶入地鐵內危及他人安全,地鐵在每個進站口設置安檢站對所有過往人員物品進行檢查。雖然避免數據錯誤的最主要方法就是檢查,但全流程無休止的數據檢查顯然是費時費力且效率低的,我們其實也可以在數據流入流出的關鍵節點設立「安檢站」,只在這個時候進行數據檢查。
一般我會在這些地方設立「安檢站」:
幾種行之有效的檢查方法:
確保數據准確的幾個日常習慣除了上述成體系的錯誤規避手段外,幾個日常的好習慣也可以讓我們盡可能的離錯誤遠一點:
以上,是確保數據准確的大致經驗總結,幾句最關鍵的話再重復嘮叨一下:
數據處理的准確性校驗一直是個難題,是否存在一些針對據處理准確性的通用做法呢?
下面是一些對於數據進行計算處理後,保證數據准確性的個人實踐:
對於大部分數據來說,數據處理可以分為以下 五個步驟 :
1.數據採集;2.數據傳輸(實時/批量);3.數據建模/存儲;4.數據計算/分析;5.數據可視化展示/挖掘
針對上面五點分別展開介紹:
一、數據採集
通常數據處理之前會有數據採集的過程,數據採集會涉及到多數據來源,每中數據來源由於格式等不一致,需要特殊處理。
1.針對不通的數據源,需要做到每個數據源獲取 數據能夠獨立。
2.採集過程需要監控,傳輸之前如有條件,可以做到本地有備份數據,便於異常查找時進行數據比對。
二、數據傳輸(實時/批量)
數據源本地已經做到有備份的情況下,對於傳輸異常的時候,需要 支持重試 ,存儲端需要支持去重。
三、數據建模/存儲
數據存儲可以針對結果集合進行冗餘分類存儲,便於數據進行比對,針對存儲需要進行副本備份,同時數據可以考慮按生效記錄進行疊加存儲,支持回溯 歷史 的存儲結構進行存儲。
四、數據計算/分析/挖掘
數據進行計算,分析的時候需要進行步驟分解,便於准確性的分析和統計
1.計算之前,支持測算,同時支持數據進行分批計算,需要能導出本批次清單基礎數據(例如人員或者id),便於數據核對。
2.計算之中,支持快速少量指定的典型數據測算,支持選擇,是否存儲參與計算過程的全部的中間變數。
3.計算之後,可以選擇,支持導出本次計算過程中的所有參與變數和中間變數參數,可以線下根據數據列表對應的參數,進行計算,從而進行數據准確性的核對。
計算過程中,支持針對有問題的數據ID進行染色,染色後的數據,所有的中間過程變數全部進行列印輸出。
五、數據可視化展示
可視化挖掘過程,需要主要前台圖形化界面的數據量