互聯網高併發分佈式集羣緩存JavaWeb開發J2EE項目開發java架構師

互聯網行業是大勢所趨,從招聘工資水平即可看出,那麼如何提升自我技能,滿足互聯網行業技能要求?需要以目標爲導向,進行技能提升,本文主要針對高併發分佈式系統設計、架構(數據一致性)做了分析,祝各位早日走上屬於自己的"成金之路"。

 

目錄:
問題分析
概念解讀
Most Simple原理解讀
eBey、去哪兒、蘑菇街分佈式事務案例分析

參考資料

1.問題解析    
要想做架構,必須識別出問題,即是誰的問題,什麼問題。
明顯的,分佈式架構解決的是高併發的問題,高併發下服務高可用和數據一致性問題問題;當規模規模較小時,單庫HA即可滿足請求,當業務規模持續增加,單庫已經無法滿足業務需求,業界主流做法,是對業務進行分表、分庫,那麼原來的有些業務,現在則要在一個事務中,保證兩個庫同時操作成功或操作不成功(一個庫成功,一個庫失敗,要麼重新嘗試失敗庫操作直到成功,要麼回滾成功庫)。隨之而來的問題既是如何保證分庫時業務操作的數據一致性。理解高併發分佈式架構、分佈式系統數據一致性的問題、起源是第一步。

這裏多囉嗦一點,分庫後,每個庫可以採取不同的語言,以時下很流行的微服務向外提供服務;但是業務量不大的情況下,使用微服務到增加了複雜性及技術成本。明白技術的起源,針對不同的業務量,採取適當的架構、以最恰當的方式承載業務,是架構師必須具備的能力。

 

2.常見概念解讀:

a.關係型數據庫通常具有ACID特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。

b.Base(basically available, soft state, eventually consistent):一種 Acid 的替代方案,BASE 的可用性是通過支持局部故障而不是系統全局故障來實現的。化學理論中ACID是酸、Base恰好是鹼。

c.CAP定律:在分佈式系統中,同時滿足"CAP定律"中的"一致性"、"可用性"和"分區容錯性"三者是不可能的。

d.強一致:當更新操作完成之後,任何多個後續進程或者線程的訪問都會返回最新的更新過的值。這種是對用戶最友好的,就是用戶上一次寫什麼,下一次就保證能讀到什麼。根據 CAP 理論,這種實現需要犧牲可用性,常見的RDBMS。

e.弱一致性:系統並不保證續進程或者線程的訪問都會返回最新的更新過的值。系統在數據寫入成功之後,不承諾立即可以讀到最新寫入的值,也不會具體的承諾多久之後可以讀到。

f.最終一致性:弱一致性的特定形式。系統保證在沒有後續更新的前提下,系統最終返回上一次更新操作的值。在沒有故障發生的前提下,不一致窗口的時間主要受通信延遲,系統負載和複製副本的個數影響。DNS 是一個典型的最終一致性系統。

爲保證可用性,互聯網分佈式架構將強一致性需求轉換成最終一致性的需求,並通過系統執行冪等性的保證,保證數據的最終一致性。

 

冪等性(Idempotence):分佈式架構的基石,即同一個操作無論請求多少次,其結果都相同。

典型的是HTTP,Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.

 

每個概念實際所解決的是人遇到的某個特定的問題,發現其背後所代表的問題,是理解高併發分佈式架構、分佈式系統數據一致性第二步。

 

3.Most Simple原理解讀

假設有一個從賬戶取錢的遠程API(可以是HTTP的,也可以不是),我們暫時用類函數的方式記爲:

bool withdraw(account_id, amount)
withdraw的語義是從account_id對應的賬戶中扣除amount數額的錢;如果扣除成功則返回true,賬戶餘額減少amount;如果扣除失敗則返回false,賬戶餘額不變。

值得注意的是:和本地環境相比,我們不能輕易假設環境的可靠性

一種典型的場景是withdraw請求已經被服務器端正確處理,但服務器端的返回結果由於網絡等原因被掉丟了,導致客戶端無法得知處理結果。如果是在網頁上,一些不恰當的設計可能會使用戶認爲上一次操作失敗了,然後刷新頁面,這就導致了withdraw被調用兩次,賬戶也被多扣了一次錢。如圖1所示:

non-idempotent

一種更輕量級的解決方案是冪等設計。我們可以通過一些技巧把withdraw變成冪等的,比如:


int create_ticket() 
bool idempotent_withdraw(ticket_id, account_id, amount)
create_ticket的語義是獲取一個服務器端生成的唯一的處理號ticket_id,它將用於標識後續的操作。idempotent_withdraw和withdraw的區別在於關聯了一個ticket_id,一個ticket_id表示的操作至多隻會被處理一次,每次調用都將返回第一次調用時的處理結果。這樣,idempotent_withdraw就符合冪等性了,客戶端就可以放心地多次調用。

基於冪等性的解決方案中一個完整的取錢流程被分解成了兩個步驟:1.調用create_ticket()獲取ticket_id;2.調用idempotent_withdraw(ticket_id, account_id, amount)。雖然create_ticket不是冪等的,但在這種設計下,它對系統狀態的影響可以忽略,加上idempotent_withdraw是冪等的,所以任何一步由於網絡等原因失敗或超時,客戶端都可以重試,直到獲得結果。如圖所示:

互聯網高併發分佈式集羣緩存JavaWeb開發J2EE項目開發java架構師


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章