分佈式的一些思考?

一、前言

最近系統上遇到一些問題,我又仔細去思考了一下CAP相關方面的東西,有點感悟想寫篇文章,來好好思索下CAP這個東西;

二、先聊聊一聊我遇到的問題?

簡單的說說我的場景,MQ推送消息過來以後寫入redis,然後多個進程去消費redis中的數據,最後處理完成進入ES。最近更改一些需求,要求必須是隻能生成一條明細,我們系統可能推送多次,我們通過緩存是可以判斷出最早的一條,但是系統上線以後還是會出現多條,後來經過排查發現原來是MQ時序問題,導致最終生成2條明細,後來我採用使用唯一ID處理這個問題,中間還思考通過ES版本號處理的這種方式,最終還是採用唯一Id處理,這裡我們不比較這兩種方式好壞。還是要關注我們說主題分佈式的思考,我只想通過我這例子來說說CAP到底是處理什麼問題的?

分佈式的一些思考?

上圖基本就是我們處理數據的流程,我省去了很多東西,比如分佈式鎖、緩存呀等等這些東西。我們單純就藉助這個模型來說說分佈式的問題,A、B、C代表進程,我們都是分開部署多個節點在不同的機器上,類似於很多單體Web程序部署多臺機器上通過Nginx分發處理請求,我們這些也都可以算是分佈式系統,我們只是單純自己玩,不相互聯繫而已,以一個不恰當的比喻來說最熟悉的陌生人。那CAP是處理什麼問題的,大家可以看下這篇文章,看不懂可以翻譯下,當然我就是屬於看不懂的,哈哈。摘錄下其中比較重要的話,翻譯過來以後是:

在一個分佈式系統(指互相連接並共享數據的節點的集合)中,在讀/寫操作的時候,一致性(Consistence)、可用性(Availability)、分區容錯性(Partition Tolerance)只能同時保證其中兩者,比如我們上面說兩種情況,雖然分佈式有讀寫操作,但是系統之間沒有共享數據和相互連接,所以我們可以保證這3者同時存在。這裡我們思考一個場景來解釋下什麼是共享數據和相互連接,就拿我們經常使用的淘寶買東西來說吧,當你買一件東西的時候,需要查看你的餘額,然後發生扣款,打入到第三方賬戶種,這裡你的錢就是共享數據和相互連接,明白這兩個概念我們就來解釋解釋CAP的概念。

一致性(Consistence):其實就是類似於事務的隔離性,客戶端不會讀取到正在提交的事務,只有提交成功以後才客戶端才可以查詢到變更的信息,舉個形象一點的例子來說,淘寶在你下單成功以後才會扣你的錢,不會下單失敗了扣你的錢,在你下單的過程中你的賬戶裡面的錢是不會動的,這就是一致性;

可用性(Availability):非故障的節點在合理的時間內返回合理的響應(不是錯誤和超時的響應),這個我感覺不需要舉例子吧,就是系統的每個功能都能正常的返回結果;

分區容錯性(Partition Tolerance):當發生網絡分區後,系統依然能夠發揮原來的作用,舉個例子就是當ES某個節點掛掉的時候我們依然可以正常使用,這個例子可能不是恰當,但是能說明分區容錯性的重要性,後面我們再來討論下ES的CAP設計,這還是一件蠻有意思的事情;

在瞭解這3者之間的關係時候,我們就來思考下為什麼只能三選二?在分佈式系統中,必須要多臺機器部署才能叫做分佈式,多臺機器相互聯繫的時候可能會發生網絡或者其他一些故障,我們在設計的時候必須考慮到P,這個時候我們就該考慮C和A為什麼不能共存,這二者本就是矛和盾的存在,當發生分區故障的時候,為了保證C,系統必須禁止寫入,當有寫入的請求的時候,系統就會返回錯誤,這個時候就和A衝突掉了,A要求的是不能是錯誤和超時響應,所以這就分佈式系統理論上不能夠選著CA,只能夠選擇CP和AP;

三、分析一波

前幾篇博客一直都是在分析ES,那我們就來分析分析ES中CAP應用,大家可以提出不同的意見,支持辯駁。之前ES系列文章中也講過ES會有腦裂的現象,這就是ES在P上的設計,這個不是我們討論的重點,我們重點是ES到底是CP還是AP?可以在這幾方面的進行討論,讀,寫去解釋下ES對於A和C的設計。

在ES讀取數據的時候有preference這個類型,默認情況下操作在可用的分片中隨機讀取,我們可以通過設置參數來控制只讀主,不懂這個大家可以參考下官方文檔,做一點深層次思考preference的設計就是A和C的權衡,當我們系統要求很高的一致性性的時候我們就可以只讀主分片,當要求不高的時候我們就可以隨機讀取,具體大家使用可以根據自己系統進行選擇;

在之前的系列中也講過ES的translog(事務日誌)機制和flush機制,其實這裡面的設計也是ES對C和A的選擇,只是權力交給了我們,大傢俱體可以參考官方文檔,這裡我們也做下介紹,

TransLog

index.translog.durability:如果設為 async,默認情況下,ES 會每隔五秒對 TransLog 執行一次 fsync 和 commit 的操作;如果設為 request(default),則在每次真正執行index、delete、update 或者 bulk index 操作前立刻將 TransLog fsync 到每一個主分片和副本分片中,並返回成功;

index.translog.sync_interval:設置為async時,每次持久化間隔的時間;

還有上面我們講述的ES鎖的控制,有樂觀和悲觀鎖,樂觀鎖是通過版本控制也就是我們常用的最終一致,悲觀鎖是強一致,設計方面的東西就理解到這裡,其實我認為ES跟偏向於AP的設計,畢竟如果對這些不是很瞭解的話,他都是默認高可用,其實某些情況下還是不要過多執著於這個系統到底是CP還是AP,畢竟有些特殊情況嘛。


分享到:


相關文章: