一般來說,就是如果系統不是嚴格要求緩存+資料庫必須一致性的話,緩存可以稍微的跟資料庫偶爾有不一致的情況,最好不要做這個方案,讀請求和寫請求串列化,串到一個內存隊列里去,這樣就可以保證一定不會出現不一致的情況
串列化之後,就會導致系統的吞吐量會大幅度的降低,用比正常情況下多幾倍的機器去支撐線上的一個請求。
2. 分布式緩存中,哈希取余分區和一致性哈希分區有什麼區別
環割法(一致性 hash)環割法的原理如下:
1. 初始化的時候生成分片數量 X × 環割數量 N 的固定方式編號的字元串,例如 SHARD-1-NODE-1,並計算所有 X×N 個字元串的所有 hash 值。
2. 將所有計算出來的 hash 值放到一個排序的 Map 中,並將其中的所有元素進行排序。
3. 輸入字元串的時候計算輸入字元串的 hash 值,查看 hash 值介於哪兩個元素之間,取小於 hash 值的那個元素對應的分片為數據的分片。
數據比較
下面將通過測試對環割法和跳躍法的性能及均衡性進行對比,說明 DBLE 為何使用跳躍法代替了環割法。
數據源:現場數據 350595 條
測試經過:
1. 通過各自的測試方法執行對於測試數據的分片任務。
2. 測試方法:記錄分片結果的方差;記錄從開始分片至分片結束的時間;記錄分片結果與平均數的最大差值。
3. 由於在求模法 PartitionByString 的方法中要求分片的數量是 1024 的因數,所以測試過程只能使用 2 的指數形式進行測試,並在 PartitionByString 方法進行測試的時候不對於 MAC 地址進行截斷,取全量長度進行測試。
3. 如何保證分布式系統的消息最終一致性
針對樓主的問題:
下面我們以電商購物支付流程中,在各大參與者系統中可能會遇到分布式事務問題的場景進行詳細的分析!
參考博文:http://www.roncoo.com/article/detail/124243
4. 秒殺過程中怎麼保證redis緩存和資料庫的一致性
如果要「保證」數據的安全性,那麼會帶來開銷的進一步提升,以至於使用redis帶來的性能優勢都會喪失。正確的做法是區分不同的業務,使得並不需要「保證」數據一致性的場合,可以使用redis優化。而敏感的場合依然使用mysql。
5. 如何保證數據的一致性
數據一致性通常指關聯數據之間的邏輯關系是否正確和完整。而數據存儲的一致性模型則可以認為是存儲系統和數據使用者之間的一種約定。如果使用者遵循這種約定,則可以得到系統所承諾的訪問結果常用的一致性模型有:
a、嚴格一致性(linearizability, strict/atomic Consistency):讀出的數據始終為最近寫入的數據。這種一致性只有全局時鍾存在時才有可能,在分布式網路環境不可能實現。
b、順序一致性(sequential consistency):所有使用者以同樣的順序看到對同一數據的操作,但是該順序不一定是實時的。
c、因果一致性(causal consistency):只有存在因果關系的寫操作才要求所有使用者以相同的次序看到,對於無因果關系的寫入則並行進行,無次序保證。因果一致性可以看做對順序一致性性能的一種優化,但在實現時必須建立與維護因果依賴圖,是相當困難的。
d、管道一致性(PRAM/FIFO consistency):在因果一致性模型上的進一步弱化,要求由某一個使用者完成的寫操作可以被其他所有的使用者按照順序的感知到,而從不同使用者中來的寫操作則無需保證順序,就像一個一個的管道一樣。 相對來說比較容易實現。
e、弱一致性(weak consistency):只要求對共享數據結構的訪問保證順序一致性。對於同步變數的操作具有順序一致性,是全局可見的,且只有當沒有寫操作等待處理時才可進行,以保證對於臨界區域的訪問順序進行。在同步時點,所有使用者可以看到相同的數據。
f、 釋放一致性(release consistency):弱一致性無法區分使用者是要進入臨界區還是要出臨界區, 釋放一致性使用兩個不同的操作語句進行了區分。需要寫入時使用者acquire該對象,寫完後release,acquire-release之間形成了一個臨界區,提供 釋放一致性也就意味著當release操作發生後,所有使用者應該可以看到該操作。
g、最終一致性(eventual consistency):當沒有新更新的情況下,更新最終會通過網路傳播到所有副本點,所有副本點最終會一致,也就是說使用者在最終某個時間點前的中間過程中無法保證看到的是新寫入的數據。可以採用最終一致性模型有一個關鍵要求:讀出陳舊數據是可以接受的。
h、delta consistency:系統會在delta時間內達到一致。這段時間內會存在一個不一致的窗口,該窗口可能是因為log shipping的過程導致。這是書上的原話。。我也搞不很清楚。。 資料庫完整性(Database Integrity)是指資料庫中數據的正確性和相容性。資料庫完整性由各種各樣的完整性約束來保證,因此可以說資料庫完整性設計就是資料庫完整性約束的設計。包括實體完整性。域完整性。參照完整性。用戶定義完整性。可以主鍵。check約束。外鍵來一一實現。這個使用較多。
6. 分布式redis怎麼保證數據一致性
Redis 默認是單機環境使用的。數據量較大時需要shard(多機環境),這個時候要用ShardedJedis。ShardedJedis是基於一致性哈希演算法實現的分布式Redis集群客戶端
7. chcahe 如何保證分布式緩存數據一致性
VPLEX的技術核心是「分布式緩存一致性」,下圖則是「分布式緩存一致性」技術的工作機制示意:正是因為這項核心技術優勢,使得VPLEX方案和目前所有廠商的虛擬化方案截然不同,並能夠實現異地的數據中心整合。對跨數據中心的所有負載實現跨引擎的平攤或者實時遷移,來自任何一個主機的I/O請求可以通過任何一個引擎得到響應。
緩存一致性的記錄目錄使用少量的元數據,記錄下哪個數據塊屬於哪個引擎更新的,以及在何時更新過,並通過4K大小的數據塊告訴在集群中的所有其他的引擎。在整個過程中實際發生的溝通過程,遠遠比實際上正在更新數據塊少很多。
分布式緩存一致性數據流示意圖:上方是一個目錄,記錄下左側的主機讀取緩存A的操作,並分發給所有引擎,右側主機需要讀取該數據塊時,會先通過目錄查詢,確定該數據塊所屬的引擎位置,讀取請求會直接發送給引擎,並直接從數據塊所在的緩存上讀取。
當一個讀請求進入時,VPLEX會自動檢查目錄,查找該數據塊所屬的引擎,一旦確定該數據塊所屬的引擎位置,讀的請求會直接發送給該引擎。一旦一個寫入動作完成,並且目錄表被修改,這時另一個讀請求從另一個引擎過來,VPLEX會檢查目錄,並且直接從該引擎的緩存上讀取。如果該數據仍然在緩存上,則完全沒必要去磁碟上讀取。
如上圖,來自圖中左側主機的操作,由Cache A服務,會記錄一個更新狀態,並分發給所有所有引擎知道。如果讀取的需求來自最右側的伺服器,首先通過目錄查詢。通過這種技術可以實現所有引擎一致性工作,而且這個技術不僅可以跨引擎還可以跨VPLEX集群,而VPLEX集群可以跨區域,因此緩存一致性也可以跨區域部署。
分布式緩存一致性技術使VPLEX相比傳統的虛擬化方案擁有更高的性能和可靠性,並實現異地數據中心的虛擬化整合
對傳統的虛擬化架構來說,如果虛擬化的I/O集群中有一個節點壞了,那麼性能就會降低一半,而且實際情況降低不止一半。因為壞了一個節點,這個節點緩存一般會被寫進去。因為沒有緩存,操作會直接寫到硬碟里。如果圖中中心這個節點壞掉,那主機所有的可用性都沒有了。而VPLEX如果有一個引擎或者一個控制器壞掉了,那這個引擎的負載會均攤到其他活動引擎上。這樣總體來講用戶可以維持可預知性能,性能降低也不那麼明顯。
8. 怎麼保證數據一致性
數據一致性通常指關聯數據之間的邏輯關系是否正確和完整。而數據存儲的一致性模型則可以認為是存儲系統和數據使用者之間的一種約定。如果使用者遵循這種約定,則可以得到系統所承諾的訪問結果常用的一致性模型有:
a、嚴格一致性(linearizability, strict/atomic Consistency):讀出的數據始終為最近寫入的數據。這種一致性只有全局時鍾存在時才有可能,在分布式網路環境不可能實現。
b、順序一致性(sequential consistency):所有使用者以同樣的順序看到對同一數據的操作,但是該順序不一定是實時的。
c、因果一致性(causal consistency):只有存在因果關系的寫操作才要求所有使用者以相同的次序看到,對於無因果關系的寫入則並行進行,無次序保證。因果一致性可以看做對順序一致性性能的一種優化,但在實現時必須建立與維護因果依賴圖,是相當困難的。
9. 分布式存儲中,怎樣使用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、節點失效、通信失敗等問題。