您好,登錄后才能下訂單哦!
這篇文章主要講解了“web分布式系統(tǒng)的基本概念是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“web分布式系統(tǒng)的基本概念是什么”吧!
小明的公司又3個系統(tǒng):系統(tǒng)A,系統(tǒng)B和系統(tǒng)C,這三個系統(tǒng)所做的業(yè)務不同,被部署在3個獨立的機器上運行,他們之間互相調用(當然是跨域網(wǎng)絡的),通力合作完成公司的業(yè)務流程。
將不同的業(yè)務分部在不同的地方,就構成了一個分布式的系統(tǒng),現(xiàn)在問題來了,系統(tǒng)A是整個分布式系統(tǒng)的臉面,用戶直接訪問,用戶訪問量大的時候要么是速度巨慢,要么直接掛掉,怎么辦?
由于系統(tǒng)A只有一份,所以會引起單點失敗。。。
小明的公司不差錢,就多買幾臺機器吧, 小明把系統(tǒng)A一下子部署了好幾份(例如下圖的3個服務器),每一份都是系統(tǒng)A的一個實例,對外提供同樣的服務,這樣,就不怕其中一個壞掉了,還有另外兩個呢。
這三個服務器的系統(tǒng)就組成了一個集群。
可是對用戶來說,一下子出現(xiàn)這么多系統(tǒng)A,每個系統(tǒng)的IP地址都不一樣,到底訪問哪一個呢?
如果所有人都訪問服務器1.1,那服務器1.1會被累死,剩下兩個閑死,成了浪費錢的擺設
小明要盡可能的讓3個機器上的系統(tǒng)A工作均衡一些,比如有3萬個請求,那就讓3個服務器各處理1萬個(理想情況),這叫負載均衡
很明顯,這個負載均衡的工作最好獨立出來,放到獨立的服務器上(例如nginx):
后來小明發(fā)現(xiàn),這個負載均衡的服務器雖然工作內容簡單,就是拿到請求,分發(fā)請求,但是它還是有可能掛掉,單點失敗還是會出現(xiàn)。
沒辦法,只好把負載均衡也搞成一個集群,bug和系統(tǒng)A的集群有兩點不同:
1.這個新的集群中雖然有兩個機器,但是我們可以用某種辦法,讓這個機器對外只提供一個IP地址,也就是用戶看到的好像只有一個機器。
2.同一時刻,我們只讓一個負載均衡的機器工作,另外一個原地待命,如果工作的那個拐到了,待命的那個就頂上去。
如果3個系統(tǒng)A的實例還是滿足不了大量請求,例如雙十一,可以申請增加服務器,雙十一過后,新增的服務器閑置,成了擺設,于是小明決定嘗試云計算,在云端可以輕松的創(chuàng)建,刪除虛擬的服務器,那樣就可以輕松的隨著用戶的請求動圖的增減服務器了。
上面的系統(tǒng)看起來很美好,但是做了一個不切實際的假設:
所有的服務都是無狀態(tài)的,換句話說,假設用戶的兩次請求直接是沒有關聯(lián)的。
但是現(xiàn)實是,大部分服務都是有狀態(tài)的,例如購物車。
用戶訪問系統(tǒng),在服務器上創(chuàng)建了一個購物車,并向其中加了幾個商品,然后服務器1.1掛掉了,用戶后續(xù)訪問就找不到服務器1.1了,這時候就要做失效轉移,讓另外幾個服務器去接管,去處理用戶的請求。
可是問題來了,在服務器1.2,1.3上有用戶的購物車嗎?如果沒有,用戶就會抱怨,我剛創(chuàng)建的購物車哪里去了?
還有更嚴重的,假設用戶登錄過得信息保存到了該服務器1.1上登錄的,用戶登錄過的信息保存到了該服務器的session中,現(xiàn)在這個服務器掛了,用的session就不見了,會把用戶踢到了登錄界面,讓用戶再次登錄!
處理不好狀態(tài)的問題,集群的威力就大打折扣,無法完成真正的失效轉移,甚至無法使用。
一種辦法是把狀態(tài)信息在集群的各個服務器之間復制,讓集群的各個服務器達成一致,誰來干這個事情?只能像Webspher,Weblogic這樣的應用服務器了。
還有一種辦法, 就是把狀態(tài)信息幾種存儲在一個地方,讓集群服務器的各個服務器都能訪問到:
小明聽說Redis不錯,那就用Redis來保存吧!
認識分布式架構
隨著計算機系統(tǒng)規(guī)模變得越來越大,將所有的業(yè)務單元集中部署在一個或若干個大型機上的體系結構,已經越來越不能滿足當今計算機系統(tǒng),尤其是大型互聯(lián)網(wǎng)系統(tǒng)的快速發(fā)展,各種靈活多變的系統(tǒng)架構模型層出不窮。分布式的處理方式越來越受到業(yè)界的青睞——計算機系統(tǒng)正在經歷一場前所未有的從集中式向分布式架構的變革。
集中式系統(tǒng)
所謂的集中式系統(tǒng)就是指由一臺或多臺主計算機組成中心節(jié)點,數(shù)據(jù)集中存儲于這個中心節(jié)點中,并且整個系統(tǒng)的所有業(yè)務單元都集中部署在這個中心節(jié)點上,系統(tǒng)的所有功能均由其集中處理。
集中式系統(tǒng)的最大的特點就是部署結構非常簡單,底層一般采用從IBM、HP等廠商購買到的昂貴的大型主機。因此無需考慮如何對服務進行多節(jié)點的部署,也就不用考慮各節(jié)點之間的分布式協(xié)作問題。但是,由于采用單機部署,很可能帶來系統(tǒng)大而復雜、難于維護、發(fā)生單點故障(單個點發(fā)生故障的時候會波及到整個系統(tǒng)或者網(wǎng)絡,從而導致整個系統(tǒng)或者網(wǎng)絡的癱瘓)、擴展性差等問題。
分布式系統(tǒng)
分布式系統(tǒng)是一個硬件或軟件組件分布在不同的網(wǎng)絡計算機上,彼此之間僅僅通過消息傳遞進行通信和協(xié)調的系統(tǒng)。簡單來說就是一群獨立計算機集合共同對外提供服務,但是對于系統(tǒng)的用戶來說,就像是一臺計算機在提供服務一樣。分布式意味著可以采用更多的普通計算機(相對于昂貴的大型機)組成分布式集群對外提供服務。計算機越多,CPU、內存、存儲資源等也就越多,能夠處理的并發(fā)訪問量也就越大。
從分布式系統(tǒng)的概念中我們知道,各個主機之間通信和協(xié)調主要通過網(wǎng)絡進行,所以分布式系統(tǒng)中的計算機在空間上幾乎沒有任何限制,這些計算機可能被放在不同的機柜上,也可能被部署在不同的機房中,還可能在不同的城市中,對于大型的網(wǎng)站甚至可能分布在不同的國家和地區(qū)。但是,無論空間上如何分布,一個標準的分布式系統(tǒng)應該具有以下幾個主要特征:
分布式系統(tǒng)中的多臺計算機之間在空間位置上可以隨意分布,同時,機器的分布情況也會隨時變動。
分布式系統(tǒng)中的計算機沒有主/從之分,即沒有控制整個系統(tǒng)的主機,也沒有被控制的從機,組成分布式系統(tǒng)的所有計算機節(jié)點都是對等的。副本(Replica)是分布式系統(tǒng)最常見的概念之一,指的是分布式系統(tǒng)對數(shù)據(jù)和服務提供的一種冗余方式。在常見的分布式系統(tǒng)中,為了對外提供高可用的服務,我們往往會對數(shù)據(jù)和服務進行副本處理。數(shù)據(jù)副本是指在不同節(jié)點上持久化同一份數(shù)據(jù),當某一個節(jié)點上存儲的數(shù)據(jù)丟失時,可以從副本上讀取該數(shù)據(jù),這是解決分布式系統(tǒng)數(shù)據(jù)丟失問題最為有效的手段。另一類副本是服務副本,指多個節(jié)點提供同樣的服務,每個節(jié)點都有能力接收來自外部的請求并進行相應的處理。
在一個計算機網(wǎng)絡中,程序運行過程的并發(fā)性操作是非常常見的行為。例如同一個分布式系統(tǒng)中的多個節(jié)點,可能會并發(fā)地操作一些共享的資源,如何準確并高效地協(xié)調分布式并發(fā)操作也成為了分布式系統(tǒng)架構與設計中最大的挑戰(zhàn)之一。
在分布式系統(tǒng)中,很難定義兩個事件究竟誰先誰后,原因就是因為分布式系統(tǒng)缺乏一個全局的時鐘序列控制。
組成分布式系統(tǒng)的所有計算機,都有可能發(fā)生任何形式的故障。除非需求指標允許,在系統(tǒng)設計時不能放過任何異常情況。
分布式系統(tǒng)需要在各個節(jié)點之間進行網(wǎng)絡通信,因此網(wǎng)絡通信都會伴隨著網(wǎng)絡不可用的風險或是系統(tǒng)不可用都會導致最終分布式系統(tǒng)無法順利完成一次網(wǎng)絡通信。另外,即使分布式系統(tǒng)各節(jié)點之間的網(wǎng)絡通信能夠正常進行,其延時也會遠大于單機操作,會影響消息的收發(fā)的過程,因此消息丟失和消息延遲變得非常普遍。
當網(wǎng)絡由于發(fā)生異常情況,導致分布式系統(tǒng)中部分節(jié)點之間的網(wǎng)絡延時不斷增大,最終導致組成分布式系統(tǒng)的所有節(jié)點中,只有部分節(jié)點之間能夠進行正常通信,而另一些節(jié)點則不能——我們將這個現(xiàn)象稱為網(wǎng)絡分區(qū),就是俗稱的“腦裂”。當網(wǎng)絡分區(qū)出現(xiàn)時,分布式系統(tǒng)會出現(xiàn)局部小集群,在極端情況下,這些局部小集群會獨立完成原本需要整個分布式才能完成的功能,這就對分布式一致性提出類非常大的挑戰(zhàn)。
分布式系統(tǒng)的每一次請求與響應,存在特有的“三態(tài)”概念,即成功、失敗與超時。當出現(xiàn)超時現(xiàn)象時,網(wǎng)絡通信的發(fā)起方是無法確定當前請求是否被成功處理的。
節(jié)點故障則是分布式環(huán)境下另一個比較常見的問題,指的是組成分布式系統(tǒng)的服務器節(jié)點出現(xiàn)的宕機或“僵死”現(xiàn)象。
前言
CAP原則又稱CAP定理,指的是在一個分布式系統(tǒng)中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區(qū)容錯性)這三個基本需求,最多只能同時滿足其中的2個。
初探分布式理論
正文
選項 描述
Consistency(一致性) 指數(shù)據(jù)在多個副本之間能夠保持一致的特性(嚴格的一致性)
Availability(可用性) 指系統(tǒng)提供的服務必須一直處于可用的狀態(tài),每次請求都能獲取到非錯的響應(不保證獲取的數(shù)據(jù)為最新數(shù)據(jù))
Partition tolerance(分區(qū)容錯性) 分布式系統(tǒng)在遇到任何網(wǎng)絡分區(qū)故障的時候,仍然能夠對外提供滿足一致性和可用性的服務,除非整個網(wǎng)絡環(huán)境都發(fā)生了故障
什么是分區(qū)?
在分布式系統(tǒng)中,不同的節(jié)點分布在不同的子網(wǎng)絡中,由于一些特殊的原因,這些子節(jié)點之間出現(xiàn)了網(wǎng)絡不通的狀態(tài),但他們的內部子網(wǎng)絡是正常的。從而導致了整個系統(tǒng)的環(huán)境被切分成了若干個孤立的區(qū)域,這就是分區(qū)。
CAP的基本場景,網(wǎng)絡中有兩個節(jié)點N1和N2,可以簡單的理解N1和N2分別是兩臺計算機,他們之間網(wǎng)絡可以連通,N1中有一個應用程序A,和一個數(shù)據(jù)庫V,N2也有一個應用程序B和一個數(shù)據(jù)庫V。現(xiàn)在,A和B是分布式系統(tǒng)的兩個部分,V是分布式系統(tǒng)的數(shù)據(jù)存儲的兩個子數(shù)據(jù)庫。
在滿足一致性的時候,N1和N2中的數(shù)據(jù)是一樣的,V0=V0。
在滿足可用性的時候,用戶不管是請求N1或者N2,都會得到立即響應。
在滿足分區(qū)容錯性的情況下,N1和N2有任何一方宕機,或者網(wǎng)絡不通的時候,都不會影響N1和N2彼此之間的正常運作。
這是分布式系統(tǒng)正常運轉的流程,用戶向N1機器請求數(shù)據(jù)更新,程序A更新數(shù)據(jù)庫V0為V1。分布式系統(tǒng)將數(shù)據(jù)進行同步操作M,將V1同步的N2中V0,使得N2中的數(shù)據(jù)V0也更新為V1,N2中的數(shù)據(jù)再響應N2的請求。
根據(jù)CAP原則定義,系統(tǒng)的一致性、可用性和分區(qū)容錯性細分如下:
一致性:N1和N2的數(shù)據(jù)庫V之間的數(shù)據(jù)是否完全一樣。
可用性:N1和N2的對外部的請求能否做出正常的響應。
分區(qū)容錯性:N1和N2之間的網(wǎng)絡是否互通。
這是正常運作的場景,也是理想的場景。作為一個分布式系統(tǒng),它和單機系統(tǒng)的最大區(qū)別,就在于網(wǎng)絡。現(xiàn)在假設一種極端情況,N1和N2之間的網(wǎng)絡斷開了,我們要支持這種網(wǎng)絡異常。相當于要滿足分區(qū)容錯性,能不能同時滿足一致性和可用性呢?還是說要對他們進行取舍?
假設在N1和N2之間網(wǎng)絡斷開的時候,有用戶向N1發(fā)送數(shù)據(jù)更新請求,那N1中的數(shù)據(jù)V0將被更新為V1。由于網(wǎng)絡是斷開的,所以分布式系統(tǒng)同步操作M,所以N2中的數(shù)據(jù)依舊是V0。這個時候,有用戶向N2發(fā)送數(shù)據(jù)讀取請求,由于數(shù)據(jù)還沒有進行同步,應用程序沒辦法立即給用戶返回最新的數(shù)據(jù)V1,怎么辦呢?
這里有兩種選擇:
第一:犧牲數(shù)據(jù)一致性,保證可用性。響應舊的數(shù)據(jù)V0給用戶。
第二:犧牲可用性,保證數(shù)據(jù)一致性。阻塞等待,直到網(wǎng)絡連接恢復,數(shù)據(jù)更新操作M完成之后,再給用戶響應最新的數(shù)據(jù)V1。
這個過程,證明了要滿足分區(qū)容錯性的分布式系統(tǒng),只能在一致性和可用性兩者中,選擇其中一個。
通過CAP理論,我們知道無法同時滿足一致性、可用性和分區(qū)容錯性這三個特性,那要舍棄哪個呢?
3.1. CA without P
如果不要求P(不允許分區(qū)),則C(強一致性)和A(可用性)是可以保證的。但其實分區(qū)不是你想不想的問題,而是始終會存在,因此CA的系統(tǒng)更多的是允許分區(qū)后各子系統(tǒng)依然保持CA。
3.2. CP without A
如果不要求A(可用),相當于每個請求都需要在Server之間強一致,而P(分區(qū))會導致同步時間無限延長,如此CP也是可以保證的。很多傳統(tǒng)的數(shù)據(jù)庫分布式事務都屬于這種模式。
3.3. AP wihtout C
要高可用并允許分區(qū),則需放棄一致性。一旦分區(qū)發(fā)生,節(jié)點之間可能會失去聯(lián)系,為了高可用,每個節(jié)點只能用本地數(shù)據(jù)提供服務,而這樣會導致全局數(shù)據(jù)的不一致性?,F(xiàn)在眾多的NoSQL都屬于此類。
對于多數(shù)大型互聯(lián)網(wǎng)應用的場景,主機眾多、部署分散。而且現(xiàn)在的集群規(guī)模越來越大,所以節(jié)點故障、網(wǎng)絡故障是常態(tài)。這種應用一般要保證服務可用性達到N個9,即保證P和A,只有舍棄C(退而求其次保證最終一致性)。雖然某些地方會影響客戶體驗,但沒達到造成用戶流程的嚴重程度。
對于涉及到錢財這樣不能有一絲讓步的場景,C必須保證。網(wǎng)絡發(fā)生故障寧可停止服務,這是保證CA,舍棄P。貌似這幾年國內銀行業(yè)發(fā)生了不下10起事故,但影響面不大,報到也不多,廣大群眾知道的少。還有一種是保證CP,舍棄A,例如網(wǎng)絡故障時只讀不寫。
孰優(yōu)孰劣,沒有定論,只能根據(jù)場景定奪,適合的才是最好的。
前言
BASE理論是由eBay架構師提出的。BASE是對CAP中一致性和可用性權衡的結果,其來源于對大規(guī)?;ヂ?lián)網(wǎng)分布式系統(tǒng)實踐的總結,是基于CAP定律逐步演化而來。其核心思想是即使無法做到強一致性,但每個應用都可以根據(jù)自身業(yè)務特點,才用適當?shù)姆绞絹硎瓜到y(tǒng)打到最終一致性。
正文
實際上,不是為了P(分區(qū)容錯性),必須在C(一致性)和A(可用性)之間任選其一。分區(qū)的情況很少出現(xiàn),CAP在大多時間能夠同時滿足C和A。
對于分區(qū)存在或者探知其影響的情況下,需要提供一種預備策略做出處理:
探知分區(qū)的發(fā)生;
進入顯示的分區(qū)模式,限制某些操作;
啟動恢復過程,恢復數(shù)據(jù)一致性,補償分區(qū)發(fā)生期間的錯誤。
BASE理論簡介
BASE理論是Basically Available(基本可用),Soft State(軟狀態(tài))和Eventually Consistent(最終一致性)三個短語的縮寫。
其核心思想是:
既是無法做到強一致性(Strong consistency),但每個應用都可以根據(jù)自身的業(yè)務特點,采用適當?shù)姆绞絹硎瓜到y(tǒng)達到最終一致性(Eventual consistency)。
基本可用(Basically Available)
軟狀態(tài)(Soft State)
最終一致性(Eventually Consistent)
下面展開討論:
什么是基本可用呢?假設系統(tǒng),出現(xiàn)了不可預知的故障,但還是能用,相比較正常的系統(tǒng)而言:
響應時間上的損失:正常情況下的搜索引擎0.5秒即返回給用戶結果,而基本可用的搜索引擎可以在2秒作用返回結果。
功能上的損失:在一個電商網(wǎng)站上,正常情況下,用戶可以順利完成每一筆訂單。但是到了大促期間,為了保護購物系統(tǒng)的穩(wěn)定性,部分消費者可能會被引導到一個降級頁面。
什么是軟狀態(tài)呢?相對于原子性而言,要求多個節(jié)點的數(shù)據(jù)副本都是一致的,這是一種“硬狀態(tài)”。
軟狀態(tài)指的是:允許系統(tǒng)中的數(shù)據(jù)存在中間狀態(tài),并認為該狀態(tài)不影響系統(tǒng)的整體可用性,即允許系統(tǒng)在多個不同節(jié)點的數(shù)據(jù)副本存在數(shù)據(jù)延時。
上面說軟狀態(tài),然后不可能一直是軟狀態(tài),必須有個時間期限。在期限過后,應當保證所有副本保持數(shù)據(jù)一致性,從而達到數(shù)據(jù)的最終一致性。這個時間期限取決于網(wǎng)絡延時、系統(tǒng)負載、數(shù)據(jù)復制方案設計等等因素。
而在實際工程實踐中,最終一致性分為5種:
3.3.1. 因果一致性(Causal consistency)
因果一致性指的是:如果節(jié)點A在更新完某個數(shù)據(jù)后通知了節(jié)點B,那么節(jié)點B之后對該數(shù)據(jù)的訪問和修改都是基于A更新后的值。于此同時,和節(jié)點A無因果關系的節(jié)點C的數(shù)據(jù)訪問則沒有這樣的限制。
3.3.2. 讀己之所寫(Read your writes)
讀己之所寫指的是:節(jié)點A更新一個數(shù)據(jù)后,它自身總是能訪問到自身更新過的最新值,而不會看到舊值。其實也算一種因果一致性。
3.3.3. 會話一致性(Session consistency)
會話一致性將對系統(tǒng)數(shù)據(jù)的訪問過程框定在了一個會話當中:系統(tǒng)能保證在同一個有效的會話中實現(xiàn) “讀己之所寫” 的一致性,也就是說,執(zhí)行更新操作之后,客戶端能夠在同一個會話中始終讀取到該數(shù)據(jù)項的最新值。
3.3.4. 單調讀一致性(Monotonic read consistency)
單調讀一致性指的是:如果一個節(jié)點從系統(tǒng)中讀取出一個數(shù)據(jù)項的某個值后,那么系統(tǒng)對于該節(jié)點后續(xù)的任何數(shù)據(jù)訪問都不應該返回更舊的值。
3.3.5. 單調寫一致性(Monotonic write consistency)
單調寫一致性指的是:一個系統(tǒng)要能夠保證來自同一個節(jié)點的寫操作被順序的執(zhí)行。
在實際的實踐中,這5種系統(tǒng)往往會結合使用,以構建一個具有最終一致性的分布式系統(tǒng)。
實際上,不只是分布式系統(tǒng)使用最終一致性,關系型數(shù)據(jù)庫在某個功能上,也是使用最終一致性的。比如備份,數(shù)據(jù)庫的復制過程是需要時間的,這個復制過程中,業(yè)務讀取到的值就是舊的。當然,最終還是達成了數(shù)據(jù)一致性。這也算是一個最終一致性的經典案例。
指事務的操作位于不同的節(jié)點上,需要保證事務的 AICD 特性。例如在下單場景下,庫存和訂單如果不在同一個節(jié)點上,就需要涉及分布式事務。
本地消息
原理
本地消息表與業(yè)務數(shù)據(jù)表處于同一個數(shù)據(jù)庫中,這樣就能利用本地事務來保證在對這兩個表的操作滿足事務特性。
在分布式事務操作的一方,它完成寫業(yè)務數(shù)據(jù)的操作之后向本地消息表發(fā)送一個消息,本地事務能保證這個消息一定會被寫入本地消息表中。
之后將本地消息表中的消息轉發(fā)到 Kafka 等消息隊列(MQ)中,如果轉發(fā)成功則將消息從本地消息表中刪除,否則繼續(xù)重新轉發(fā)。
在分布式事務操作的另一方從消息隊列中讀取一個消息,并執(zhí)行消息中的操作。
分析
本地消息表利用了本地事務來實現(xiàn)分布式事務,并且使用了消息隊列來保證最終一致性。
兩階段提交協(xié)議
2PC
可以使用 Java 提供的內置鎖來實現(xiàn)進程同步:由 JVM 實現(xiàn)的 synchronized 和 JDK 提供的 Lock。但是在分布式場景下,需要同步的進程可能位于不同的節(jié)點上,那么就需要使用分布式鎖來同步。
原理
鎖可以有阻塞鎖和樂觀鎖兩種實現(xiàn)方式,這里主要探討阻塞鎖實現(xiàn)。阻塞鎖通常使用互斥量來實現(xiàn),互斥量為 1 表示有其它進程在使用鎖,此時處于鎖定狀態(tài),互斥量為 0 表示未鎖定狀態(tài)。1 和 0 可以用一個整型值來存儲,也可以用某個數(shù)據(jù)存在或者不存在來存儲,某個數(shù)據(jù)存在表示互斥量為 1,也就是鎖定狀態(tài)。
實現(xiàn)
數(shù)據(jù)庫的唯一索引
當想要獲得鎖時,就向表中插入一條記錄,釋放鎖時就刪除這條記錄。唯一索引可以保證該記錄只被插入一次,那么就可以用這個記錄是否存在來判斷是否存于鎖定狀態(tài)。
這種方式存在以下幾個問題:
鎖沒有失效時間,解鎖失敗會導致死鎖,其他線程無法再獲得鎖。
只能是非阻塞鎖,插入失敗直接就報錯了,無法重試。
不可重入,同一線程在沒有釋放鎖之前無法再獲得鎖。
Redis 的 SETNX 指令
使用 SETNX(set if not exist)指令插入一個鍵值對,如果 Key 已經存在,那么會返回 False,否則插入成功并返回 True。
SETNX 指令和數(shù)據(jù)庫的唯一索引類似,可以保證只存在一個 Key 的鍵值對,可以用一個 Key 的鍵值對是否存在來判斷是否存于鎖定狀態(tài)。
EXPIRE 指令可以為一個鍵值對設置一個過期時間,從而避免了死鎖的發(fā)生。
Redis 的 RedLock 算法
使用了多個 Redis 實例來實現(xiàn)分布式鎖,這是為了保證在發(fā)生單點故障時仍然可用。
嘗試從 N 個相互獨立 Redis 實例獲取鎖,如果一個實例不可用,應該盡快嘗試下一個。
計算獲取鎖消耗的時間,只有當這個時間小于鎖的過期時間,并且從大多數(shù)(N/2+1)實例上獲取了鎖,那么就認為鎖獲取成功了。
如果鎖獲取失敗,會到每個實例上釋放鎖。
Zookeeper 的有序節(jié)點
Zookeeper 是一個為分布式應用提供一致服務的軟件,例如配置管理、分布式協(xié)同以及命名的中心化等,這些都是分布式系統(tǒng)中非常底層而且是必不可少的基本功能,但是如果自己實現(xiàn)這些功能而且要達到高吞吐、低延遲同時還要保持一致性和可用性,實際上非常困難。
(一)抽象模型
Zookeeper 提供了一種樹形結構級的命名空間,/app1/p_1 節(jié)點表示它的父節(jié)點為 /app1。
(二)節(jié)點類型
永久節(jié)點:不會因為會話結束或者超時而消失;
臨時節(jié)點:如果會話結束或者超時就會消失;
有序節(jié)點:會在節(jié)點名的后面加一個數(shù)字后綴,并且是有序的,例如生成的有序節(jié)點為 /lock/node-0000000000,它的下一個有序節(jié)點則為 /lock/node-0000000001,依次類推。
(三)監(jiān)聽器
為一個節(jié)點注冊監(jiān)聽器,在節(jié)點狀態(tài)發(fā)生改變時,會給客戶端發(fā)送消息。
(四)分布式鎖實現(xiàn)
創(chuàng)建一個鎖目錄 /lock;
在 /lock 下創(chuàng)建臨時的且有序的子節(jié)點,第一個客戶端對應的子節(jié)點為 /lock/lock-0000000000,第二個為 /lock/lock-0000000001,以此類推;
客戶端獲取 /lock 下的子節(jié)點列表,判斷自己創(chuàng)建的子節(jié)點是否為當前子節(jié)點列表中序號最小的子節(jié)點,如果是則認為獲得鎖;否則監(jiān)聽自己的前一個子節(jié)點,獲得子節(jié)點的變更通知后重復此步驟直至獲得鎖;
執(zhí)行業(yè)務代碼,完成后,刪除對應的子節(jié)點。
(五)會話超時
如果一個已經獲得鎖的會話超時了,因為創(chuàng)建的是臨時節(jié)點,所以該會話對應的臨時節(jié)點會被刪除,其它會話就可以獲得鎖了??梢钥吹剑琙ookeeper 分布式鎖不會出現(xiàn)數(shù)據(jù)庫的唯一索引實現(xiàn)分布式鎖的死鎖問題。
(六)羊群效應
一個節(jié)點未獲得鎖,需要監(jiān)聽自己的前一個子節(jié)點,這是因為如果監(jiān)聽所有的子節(jié)點,那么任意一個子節(jié)點狀態(tài)改變,其它所有子節(jié)點都會收到通知(羊群效應),而我們只希望它的后一個子節(jié)點收到通知。
在分布式場景下,一個用戶的 Session 如果只存儲在一個服務器上,那么當負載均衡器把用戶的下一個請求轉發(fā)到另一個服務器上,該服務器沒有用戶的 Session,就可能導致用戶需要重新進行登錄等操作。
Sticky Sessions
需要配置負載均衡器,使得一個用戶的所有請求都路由到一個服務器節(jié)點上,這樣就可以把用戶的 Session 存放在該服務器節(jié)點中。
缺點:當服務器節(jié)點宕機時,將丟失該服務器節(jié)點上的所有 Session。
Session Replication
在服務器節(jié)點之間進行 Session 同步操作,這樣的話用戶可以訪問任何一個服務器節(jié)點。
缺點:需要更好的服務器硬件條件;需要對服務器進行配置。
Persistent DataStore
將 Session 信息持久化到一個數(shù)據(jù)庫中。
缺點:有可能需要去實現(xiàn)存取 Session 的代碼。
In-Memory DataStore
可以使用 Redis 和 Memcached 這種內存型數(shù)據(jù)庫對 Session 進行存儲,可以大大提高 Session 的讀寫效率。內存型數(shù)據(jù)庫同樣可以持久化數(shù)據(jù)到磁盤中來保證數(shù)據(jù)的安全性。
算法
輪詢(Round Robin)
輪詢算法把每個請求輪流發(fā)送到每個服務器上。下圖中,一共有 6 個客戶端產生了 6 個請求,這 6 個請求按 (1, 2, 3, 4, 5, 6) 的順序發(fā)送。最后,(1, 3, 5) 的請求會被發(fā)送到服務器 1,(2, 4, 6) 的請求會被發(fā)送到服務器 2。
該算法比較適合每個服務器的性能差不多的場景,如果有性能存在差異的情況下,那么性能較差的服務器可能無法承擔過大的負載(下圖的 Server 2)。
加權輪詢(Weighted Round Robbin)
加權輪詢是在輪詢的基礎上,根據(jù)服務器的性能差異,為服務器賦予一定的權值。例如下圖中,服務器 1 被賦予的權值為 5,服務器 2 被賦予的權值為 1,那么 (1, 2, 3, 4, 5) 請求會被發(fā)送到服務器 1,(6) 請求會被發(fā)送到服務器 2。
最少連接(least Connections)
由于每個請求的連接時間不一樣,使用輪詢或者加權輪詢算法的話,可能會讓一臺服務器當前連接數(shù)過大,而另一臺服務器的連接過小,造成負載不均衡。例如下圖中,(1, 3, 5) 請求會被發(fā)送到服務器 1,但是 (1, 3) 很快就斷開連接,此時只有 (5) 請求連接服務器 1;(2, 4, 6) 請求被發(fā)送到服務器 2,只有 (2) 的連接斷開。該系統(tǒng)繼續(xù)運行時,服務器 2 會承擔過大的負載。
最少連接算法就是將請求發(fā)送給當前最少連接數(shù)的服務器上。例如下圖中,服務器 1 當前連接數(shù)最小,那么新到來的請求 6 就會被發(fā)送到服務器 1 上。
加權最少連接(Weighted Least Connection)
在最少連接的基礎上,根據(jù)服務器的性能為每臺服務器分配權重,再根據(jù)權重計算出每臺服務器能處理的連接數(shù)。
隨機算法(Random)
把請求隨機發(fā)送到服務器上。和輪詢算法類似,該算法比較適合服務器性能差不多的場景。
源地址哈希法 (IP Hash)
源地址哈希通過對客戶端 IP 哈希計算得到的一個數(shù)值,用該數(shù)值對服務器數(shù)量進行取模運算,取模結果便是目標服務器的序號。
優(yōu)點:保證同一 IP 的客戶端都會被 hash 到同一臺服務器上。
缺點:不利于集群擴展,后臺服務器數(shù)量變更都會影響 hash 結果??梢圆捎靡恢滦?Hash 改進。
實現(xiàn)
HTTP 重定向
HTTP 重定向負載均衡服務器收到 HTTP 請求之后會返回服務器的地址,并將該地址寫入 HTTP 重定向響應中返回給瀏覽器,瀏覽器收到后需要再次發(fā)送請求。
缺點:
用戶訪問的延遲會增加;
如果負載均衡器宕機,就無法訪問該站點。
DNS 重定向
使用 DNS 作為負載均衡器,根據(jù)負載情況返回不同服務器的 IP 地址。大型網(wǎng)站基本使用了這種方式做為第一級負載均衡手段,然后在內部使用其它方式做第二級負載均衡。
缺點:
DNS 查找表可能會被客戶端緩存起來,那么之后的所有請求都會被重定向到同一個服務器。
修改 MAC 地址
使用 LVS(Linux Virtual Server)這種鏈路層負載均衡器,根據(jù)負載情況修改請求的 MAC 地址。
修改 IP 地址
在網(wǎng)絡層修改請求的目的 IP 地址。
代理自動配置
正向代理與反向代理的區(qū)別:
正向代理:發(fā)生在客戶端,是由用戶主動發(fā)起的。比如,客戶端通過主動訪問代理服務器,讓代理服務器獲得需要的外網(wǎng)數(shù)據(jù),然后轉發(fā)回客戶端。
反向代理:發(fā)生在服務器端,用戶不知道代理的存在。
PAC 服務器是用來判斷一個請求是否要經過代理。
在涉及到高可用性時,經常會聽到”腦裂“,到底啥是”腦裂“?
一句話:當兩(多)個節(jié)點同時認為自已是唯一處于活動狀態(tài)的服務器從而出現(xiàn)爭用資源的情況,這種爭用資源的場景即是所謂的“腦裂”(split-brain)或”區(qū)間集群“(partitioned cluster)。
HeartBeat原理:
HeartBeat運行于備用主機上的Heartbeat可以通過以太網(wǎng)連接檢測主服務器的運行狀態(tài),一旦其無法檢測到主服務器的”心跳”則自動接管主服務器的資源。通常情況下,主、備服務器間的心跳連接是一個獨立的物理連接,這個連接可以是串行線纜、一個由”交叉線”實現(xiàn)的以太網(wǎng)連接。Heartbeat甚至可同時通過多個物理連接檢測主服務器的工作狀態(tài),而其只要能通過其中一個連接收到主服務器處于活動狀態(tài)的信息,就會認為主服務器處于正常狀態(tài)。從實踐經驗的角度來說,建議為Heartbeat配置多條獨立的物理連接,以避免Heartbeat通信線路本身存在單點故障。
在“雙機熱備”高可用(HA)系統(tǒng)中,當聯(lián)系2個節(jié)點的“心跳線”斷開時,本來為一整體、動作協(xié)調的HA系統(tǒng),就分裂成為2個獨立的個體。由于相互失去了聯(lián)系,都以為是對方出了故障,2個節(jié)點上的HA軟件像“裂腦人”一樣,“本能”地爭搶“共享資源”、爭起“應用服務”,就會發(fā)生嚴重后果:或者共享資源被瓜分、2邊“服務”都起不來了;或者2邊“服務”都起來了,但同時讀寫“共享存儲”,導致數(shù)據(jù)損壞(常見如數(shù)據(jù)庫輪詢著的聯(lián)機日志出錯)。
運行于備用主機上的Heartbeat可以通過以太網(wǎng)連接檢測主服務器的運行狀態(tài),一旦其無法檢測到主服務器的“心跳”則自動接管主服務器的資源。通常情況下,主、備服務器間的心跳連接是一個獨立的物理連接,這個連接可以是串行線纜、一個由“交叉線”實現(xiàn)的以太網(wǎng)連接。Heartbeat甚至可同時通過多個物理連接檢測主服務器的工作狀態(tài),而其只要能通過其中一個連接收到主服務器處于活動狀態(tài)的信息,就會認為主服務器處于正常狀態(tài)。從實踐經驗的角度來說,建議為Heartbeat配置多條獨立的物理連接,以避免Heartbeat通信線路本身存在單點故障。
1、串行電纜:被認為是比以太網(wǎng)連接安全性稍好些的連接方式,因為hacker無法通過串行連接運行諸如telnet、ssh或rsh類的程序,從而可以降低其通過已劫持的服務器再次侵入備份服務器的幾率。但串行線纜受限于可用長度,因此主、備服務器的距離必須非常短。
2、以太網(wǎng)連接:使用此方式可以消除串行線纜的在長度方面限制,并且可以通過此連接在主備服務器間同步文件系統(tǒng),從而減少了從正常通信連接帶寬的占用。
基于冗余的角度考慮,應該在主、備服務器使用兩個物理連接傳輸heartbeat的控制信息;這樣可以避免在一個網(wǎng)絡或線纜故障時導致兩個節(jié)點同時認為自已是唯一處于活動狀態(tài)的服務器從而出現(xiàn)爭用資源的情況,這種爭用資源的場景即是所謂的“腦裂”(split-brain)或“partitioned cluster”。在兩個節(jié)點共享同一個物理設備資源的情況下,腦裂會產生相當可怕的后果。 為了避免出現(xiàn)腦裂,可采用下面的預防措施:
添加冗余的心跳線,例如雙線條線。盡量減少“裂腦”發(fā)生機會。
啟用磁盤鎖。正在服務一方鎖住共享磁盤,“裂腦”發(fā)生時,讓對方完全“搶不走”共享磁盤資源。但使用鎖磁盤也會有一個不小的問題,如果占用共享盤的一方不主動“解鎖”,另一方就永遠得不到共享磁盤。現(xiàn)實中假如服務節(jié)點突然死機或崩潰,就不可能執(zhí)行解鎖命令。后備節(jié)點也就接管不了共享資源和應用服務。于是有人在HA中設計了“智能”鎖。即,正在服務的一方只在發(fā)現(xiàn)心跳線全部斷開(察覺不到對端)時才啟用磁盤鎖。平時就不上鎖了。
設置仲裁機制。例如設置參考IP(如網(wǎng)關IP),當心跳線完全斷開時,2個節(jié)點都各自ping一下 參考IP,不通則表明斷點就出在本端,不僅“心跳”、還兼對外“服務”的本端網(wǎng)絡鏈路斷了,即使啟動(或繼續(xù))應用服務也沒有用了,那就主動放棄競爭,讓能夠ping通參考IP的一端去起服務。更保險一些,ping不通參考IP的一方干脆就自我重啟,以徹底釋放有可能還占用著的那些共享資源。
感謝各位的閱讀,以上就是“web分布式系統(tǒng)的基本概念是什么”的內容了,經過本文的學習后,相信大家對web分布式系統(tǒng)的基本概念是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。