分布式理论,架构设计
一、分布式架構介紹
1.1 什么是分布式系統?
分布式系統是一個硬件或軟件組件分布在不同的網絡計算機上,彼此之間僅僅通過消息傳遞進行通信和協調的系統。
1.2 分布式與集群的區別
集群: 多個服務器做同一個事情/分布式: 多個服務器做不同的事情
1.3 分布式系統特性
分布性
空間隨機分布。這些計算機可以分布在不同的機房,不同的城市,甚至不同的國家。
對等性
分布式系統中的計算機沒有主/從之分,組成分布式系統的所有節點都是對等的。
并發性
同一個分布式系統的多個節點,可能會并發地操作一些共享的資源,諸如數據庫或分布式存儲。
缺乏全局時鐘
既然各個計算機之間是依賴于交換信息來進行相互通信,很難定義兩件事件的先后順序,缺乏全局始終控制序列。
故障總會發生
組成分布式的計算機,都有可能在某一時刻突然間崩掉。分的計算機越多,可能崩掉一個的幾率就越大。如果再考慮到設計程序時的異常故障,也會加大故障的概率。
處理單點故障
單點SPoF(Single Point of Failure):某個角色或者功能只有某一臺計算機在支撐,在這臺計算機上出現的故障是單點故障。
1.4 分布式系統面臨的問題
通信異常
網絡分區
節點故障
三態:成功、失敗、超時
重發
冪等:一次和多次請求某一個資源對于資源本身應該具有同樣的結果
二、分布式理論
2.1 數據一致性
分布式數據一致性,指的是數據在多份副本中存儲時,各副本中的數據是一致的。
一致性分類:
強一致性:寫入了什么,讀出來也是什么
弱一致性:不承諾立即讀取到寫入值
最終一致性:弱一致性的一種
【不一致時間窗口:系統無法保證強一致性的時間片段】
最終一致性變種:
因果一致性:(AB為因果關系)
讀己之所寫一致性
會話一致性
單調讀一致性
單調寫一致性
數據一致性模型圖
2.2 CAP定理
一致性(Consistency)
所有節點訪問時都是同一份最新的數據副本
可用性(Availability)
每次請求都能獲取到非錯的響應,但是不保證獲取的數據為最新數據
分區容錯性(Partition tolerance)
分布式系統在遇到任何網絡分區故障的時候,仍然能夠對外提供滿足一致性和可用性的服務,除非整個網絡環境都發生了故障
由于CAP不可能同時滿足,而分區容錯性對于分布式系統而言是必須的,即一般采用CP或AP
2.3 BASE定理
BASE:
Basically Available(基本可用)
Soft state(軟狀態)
Eventually consistent(最終一致性)
三、分布式一致性協議
3.1 2PC(2 Prepare Commit)
2PC流程圖
優點:原理簡單
缺點:
同步阻塞
在二階段提交的執行過程中,所有參與該事務操作的邏輯都處于阻塞狀態,即當參與者占有公共資源時,其他節點訪問公共資源會處于阻塞狀態
單點問題
若協調器出現問題,那么整個二階段提交流程將無法運轉,若協調者是在階段二中出現問題時,那么其他參與者將會一直處于鎖定事務資源的狀態中,而無法繼續完成事務操作
數據不一致
在階段二中,執行事務提交的時候,當協調者向所有的參與者發送Commit請求之后,發生了局部網絡異常或者是協調者在尚未發送完Commit請求之前自身發生了崩潰,導致最終只有部分參與者收到了Commit請求,于是會出現數據不一致的現象。
太過保守
在進行事務提交詢問的過程中,參與者出現故障而導致協調者始終無法獲取到所有參與者的響應信息的話,此時協調者只能依靠自身的超時機制來判斷是否需要中斷事務,這樣的策略過于保守,即沒有完善的容錯機制,任意一個結點的失敗都會導致整個事務的失敗。
3.2 3PC(三階段提交協議)
3PC流程圖
首先對于協調者和參與者都設置了超時機制(在2PC中,只有協調者擁有超時機制,即如果在一定時間內沒有收到參與者的消息則默認失敗),主要是避免了參與者在長時間無法與協調者節點通訊(協調者掛掉了)的情況下,無法釋放資源的問題,因為參與者自身擁有超時機制會在超時后,自動進行本地commit從而進行釋放資源。而這種機制也側面降低了整個事務的阻塞時間和范圍。
通過CanCommit、PreCommit、DoCommit三個階段的設計,相較于2PC而言,多設置了一個緩沖階段保證了在最后提交階段之前各參與節點的狀態是一致的 。
PreCommit是一個緩沖,保證了在最后提交階段之前各參與節點的狀態是一致的。
注意:一旦進入階段三,可能會出現 2 種故障:
協調者出現問題
協調者和參與者之間的網絡故障
如果出現了任一一種情況,最終都會導致參與者無法收到 doCommit 請求或者 abort 請求,針對這種情況,參與者都會在等待超時之后,繼續進行事務提交
問題:3PC協議并沒有完全解決數據一致問題。
3.3 NWR協議
NWR是一種在分布式存儲系統中用于控制一致性級別的一種策略。在亞馬遜的云存儲系統(Dynamo)中,就應用NWR來控制一致性。
N:在分布式存儲系統中,有多少份備份數據
W:代表一次成功的更新操作要求至少有w份數據寫入成功
R: 代表一次成功的讀數據操作要求至少有R份數據成功讀取
如何判斷數據的新舊?
這需要向量時鐘來配合,所以對于Dynamo來說,是通過NWR協議結合向量時鐘來共同完成一致性保證的。
NWR示例圖
3.4 Gossip協議
Gossip 是一種去中心化的分布式協議,數據通過節點像病毒一樣逐個傳播。
因為是指數級傳播,整體傳播速度非常快。
優點:
擴展性:允許節點的任意增加和減少,新增節點的狀態 最終會與其他節點一致容錯:任意節點的宕機和重啟都不會影響 Gossip 消息的傳播,具有天然的分布式系統容錯特性
去中心化:無需中心節點,所有節點都是對等的,任意節點無需知道整個網絡狀況,只要網絡連通,任意節點可把消息散播到全網
最終一致性:Gossip 協議實現信息指數級的快速傳播,因此在有新信息需要傳播時,消息可以快速地發送到全局節點,在有限的時間內能夠做到所有節點都擁有最新的數據。
缺點:
消息延遲:節點隨機向少數幾個節點發送消息,消息最終是通過多個輪次的散播而到達全網;不可避免的造成消息延遲。
消息冗余:節點定期隨機選擇周圍節點發送消息,而收到消息的節點也會重復該步驟;不可避免的引起同一節點消息多次接收,增加消息處理壓力
適合于 AP 場景的數據一致性處理
3.5 Paxos算法(重點)
自Paxos問世以來就持續壟斷了分布式一致性算法,Paxos這個名詞幾乎等同于分布式一致性。Google Chubby的作者Mike Burrows說過這個世界上只有一種一致性算法,那就是Paxos。
Paxos算法需要解決的問題就是如何在一個可能發生上述異常的分布式系統中,快速且正確地在集群內部對某個數據的值達成一致,并且保證不論發生以上任何異常,都不會破壞整個系統的一致性。
Basic Paxos
角色介紹
Client:客戶端
客戶端向分布式系統發出請求,并等待響應。例如,對分布式文件服務器中文件的寫請求
Proposer:提案發起者
提案者提倡客戶端請求,試圖說服Acceptor對此達成一致,并在發生沖突時充當協調者以推動協議向前發展
Acceptor: 決策者,可以批準提案
Acceptor可以接受(accept)提案;并進行投票, 投票結果是否通過以多數派為準, 以如果某個提案被選定,那么該提案里的value就被選定了
Learner: 最終決策的學習者
學習者充當該協議的復制因素(不參與投票)
basic paxos[活鎖問題:只需要在每個Proposer再去提案的時候隨機加上一個等待時間即可]
Basic paxos流程一共分為4個步驟:
Prepare Proposer提出一個提案,編號為N, 此N大于這個Proposer之前提出所有提出的編號, 請求Accpetor的多數人接受這個提案
Promise 如果編號N大于此Accpetor之前接收的任提案編號則接收, 否則拒絕
Accept 如果達到多數派, Proposer會發出accept請求, 此請求包含提案編號和對應的內容
Accepted 如果此Accpetor在此期間沒有接受到任何大于N的提案,則接收此提案內容, 否則忽略
Multi-Paxos
針對basic Paxos是存在一定得問題,首先就是流程復雜,實現及其困難,其次效率低(達成一致性需要2輪RPC調用)針對basic Paxos流程進行拆分為選舉和復制的過程。
Multi-Paxos在實施的時候會將Proposer,Acceptor和Learner的角色合并統稱為“服務器”。因此,最后只有“客戶端”和“服務器”。
Multi-Paxos角色疊加流程圖
3.6 Raft協議
Paxos算法的工程實現,引入主節點,通過競選確定主節點。
節點狀態:
Leader(主節點):接受 client 更新請求,寫入本地后,然后同步到其他副本
Follower(從節點):從 Leader 中接受更新請求,然后寫入本地日志文件。對客戶端提供讀請求
Candidate(候選節點):如果 follower 在一段時間內未收到 leader 心跳。則判斷 leader可能故障,發起選主提議。節點狀態從 Follower 變為 Candidate 狀態,直到選主結束
競選階段動態流程示意
Raft完整版的動畫演示:Raft
github提供的一個動畫演示:Raft Consensus Algorithm
3.7 Lease機制
解決雙主節點的問題,主要解決思路有四種:
設計能容忍雙主的分布式協議
Raft協議-通過Term版本高的同步低的
用lease機制
涉及去中心化-Gossip協議
Lease的原理:引入中心節點負責下發Lease
lease時間長短一般取經驗值1-10秒即可。太短網絡壓力大,太長則收回承諾時間過長影響可用性。
Lease機制
Lease的容錯:
主節點宕機
lease機制天生即可容忍網絡、lease接收方的出錯,時間即Lease剩余過期時長
中心節點異常
頒發者宕機可能使得全部節點沒有lease,系統處于不可用狀態,解決的方法就是使用一個小集群而不是單一節點作為頒發者。
時差問題
中心節點與主節點之間的時鐘可能也存在誤差,只需要中心節點考慮時鐘誤差即可。
四、分布式系統設計策略
4.1 心跳檢測機制
周期檢測心跳機制
Server端每間隔 t 秒向Node集群發起監測請求,設定超時時間,如果超過超時時間,則判斷“死亡”。
累計失效檢測機制
在周期檢測心跳機制的基礎上,統計一定周期內節點的返回情況(包括超時及正確返回),以此計算節點的“死亡”概率。
4.2 高可用
高可用(High Availability)是系統架構設計中必須考慮的因素之一。通常是指,經過設計來減少系統不能提供服務的時間。
系統高可用性的常用設計模式包括三種:
主備(Master-SLave)
互備(Multi-Master)
集群(Cluster)模式
4.3 高可用HA下"腦裂問題"
在高可用(HA)系統中,當聯系兩個節點的"心跳線"斷開時(即兩個節點斷開聯系時),本來為一個整體、動作協調的HA系統,就分裂成為兩個獨立的節點(即兩個獨立的個體)。
腦裂預防方案
添加冗余的心跳線 [即冗余通信的方法]
同時用兩條心跳線路 (即心跳線也HA),這樣一條線路壞了,另一個還是好的,依然能傳送心跳消息,盡量減少"腦裂"現象的發生幾率。
仲裁機制
當兩個節點出現分歧時,由第3方的仲裁者決定聽誰的。這個仲裁者,可能是一個鎖服務,一個共享盤或者其它什么東西
Lease機制
隔離(Fencing)機制
共享存儲fencing:確保只有一個Master往共享存儲中寫數據;
客戶端fencing:確保只有一個Master可以響應客戶端的請求;
Slave fencing:確保只有一個Master可以向Slave下發命令。
4.4 容錯性
容錯的處理是保障分布式環境下相應系統的高可用或者健壯性。
4.5 負載均衡
硬件:F5
軟件:Nginx
輪詢:默認方式,每個請求會按時間順序逐一分配到不同的后端服務器
weight:權重方式,在輪詢策略的基礎上指定輪詢的幾率,權重越大,接受請求越多
ip_hash:依據ip分配方式,相同的客戶端的請求一直發送到相同的服務器,以保證
session會話
least_conn:最少連接方式,把請求轉發給連接數較少的后端服務器
fair(第三方):響應時間方式,按照服務器端的響應時間來分配請求,響應時間短的優先分配
url_hash(第三方)
依據URL分配方式,按訪問url的hash結果來分配請求,使每個url定向到同一個后端服務器
五、分布式架構服務調用
服務調用
HTTP 應用協議的通信框架
HttpURLConnection
Apache Common HttpClient
OKhttp3
RestTemplate
RPC 框架
Java RMI
Hessian
Dubbo
g’RPC
跨域調用(同源(協議, 域名, 端口號相同))
在分布式系統中,會有調用其他業務系統,導致出現跨域問題,跨域實質上是瀏覽器的一種保護處理。
常見的解決方案:
缺點:不支持post請求,代碼書寫比較復雜
response.setHeader(“Access-Control-Allow-Origin”, “*”); 設置響應頭允許跨域.
Zuul是spring cloud中的微服務網關。網關: 是一個網絡整體系統中的前置門戶入口。請求首先通過網關,進行路徑的路由,定位到具體的服務節點上。可以使用zuul的過濾器的請求轉發去解決跨域問題。
六、 分布式服務治理
6.1 服務協調(分布式鎖是分布式協調技術實現的核心內容)
基于緩存(Redis等)實現分布式鎖
獲取鎖的時候,使用setnx加鎖,并使用expire命令為鎖添加一個超時時間,超過該時間則自動釋放鎖,鎖的value值為一個隨機生成的UUID, 釋放鎖的時候進行判斷。
獲取鎖的時候還設置一個獲取的超時時間,若超過這個時間則放棄獲取鎖。
釋放鎖的時候,通過UUID判斷是不是該鎖,若是該鎖,則執行delete進行鎖釋放。
基于ZooKeeper實現分布式鎖的步驟如下:
創建一個目錄mylock
線程A想獲取鎖就在mylock目錄下創建臨時順序節點
獲取mylock目錄下所有的子節點,然后獲取比自己小的兄弟節點,如果不存在,則說明當前線程順序號最小,獲得鎖
線程B獲取所有節點,判斷自己不是最小節點,設置監聽比自己次小的節點
線程A處理完,刪除自己的節點,線程B監聽到變更事件,判斷自己是不是最小的節點,如果是則獲得鎖
6.2 服務削峰
削峰從本質上來說就是更多地延緩用戶請求,以及層層過濾用戶的訪問需求,遵從“最后落地到數據庫的請求數要盡量少”的原則
消息隊列解決削峰
流量削峰漏斗:層層削峰
分層過濾的核心思想:
通過在不同的層次盡可能地過濾掉無效請求。
通過CDN過濾掉大量的圖片,靜態資源的請求。
再通過類似Redis這樣的分布式緩存過濾請求。
分層過濾的基本原則
對寫數據進行基于時間的合理分片,過濾掉過期的失效請求。
對寫請求做限流保護,將超出系統承載能力的請求過濾掉。
涉及到的讀數據不做強一致性校驗,減少因為一致性校驗產生瓶頸的問題。
對寫數據進行強一致性校驗,只保留最后有效的數據。
6.3 服務降級
當服務器壓力劇增的情況下,根據實際業務情況及流量,對一些服務和頁面有策略的不處理或換種簡單的方式處理,從而釋放服務器資源以保證核心服務正常運作或高效運作。
降級策略:
頁面降級 —— 可視化界面禁用點擊按鈕、調整靜態頁面
延遲服務 —— 如定時任務延遲處理、消息入MQ后延遲處理
寫降級 —— 直接禁止相關寫操作的服務請求
讀降級 —— 直接禁止相關讀的服務請求
緩存降級 —— 使用緩存方式來降級部分讀頻繁的服務接口
針對后端代碼層面的降級處理策略,則我們通常使用以下幾種處理措施進行降級處理:
拋異常
返回NULL
調用Mock數據
調用Fallback處理邏輯
分級降級
6.4 服務限流
多維度限流
限流算法
限流算法-計數器(固定窗口)
計數器限制每一分鐘或者每一秒鐘內請求不能超過一定的次數,在下一秒鐘計數器清零重新計算。
存在問題:
客戶端在第一分鐘的59秒請求100次,在第二分鐘的第1秒又請求了100次, 2秒內后端會受到200次請求的壓力,形成了流量突刺
限流算法-計數器(滑動窗口)
滑動窗口其實是細分后的計數器,它將每個時間窗口又細分成若干個時間片段,每過一個時間片段,整個時間窗口就會往右移動一格。時間窗口向右滑動一格,這時這個時間窗口其實已經打滿了100次,客戶端將被拒絕訪問,時間窗口劃分的越細,滑動窗口的滾動就越平滑,限流的效果就會越精確
限流算法-漏桶(削峰填谷)
漏桶算法類似一個限制出水速度的水桶,通過一個固定大小FIFO隊列+定時取隊列元素的方式實現,請求進入隊列后會被勻速的取出處理(桶底部開口勻速出水),當隊列被占滿后后來的請求會直接拒絕(水倒的太快從桶中溢出來)
限流算法-令牌桶
令牌桶算法是以一個恒定的速度往桶里放置令牌(如果桶里的令牌滿了就廢棄),每進來一個請求去桶里找令牌,有的話就拿走令牌繼續處理,沒有就拒絕請求。
令牌桶的優點是可以應對突發流量
缺點就是相對漏桶一定程度上減小了對下游服務的保護
6.5 服務熔斷(防止雪崩)
【熔斷】, 熔斷這一概念來源于電子工程中的斷路器(Circuit Breaker)。在互聯網系統中,當下游服務因訪問壓力過大而響應變慢或失敗,上游服務為了保護系統整體的可用性,可以暫時切斷對下游服務的調用。這種犧牲局部,保全整體的措施就叫做熔斷。
在固定時間窗口內,接口調用超時比率達到一個閾值,會開啟熔斷。進入熔斷狀態后,后續對該服務接口的調用不再經過網絡,直接執行本地的默認方法,達到服務降級的效果。
熔斷不可能是永久的。當經過了規定時間之后,服務將從熔斷狀態回復過來,再次接受調用方的遠程調用。
熔斷機制實現
Spring Cloud Hystrix
服務沒有故障時,熔斷器所處的狀態,對調用方的調用不做任何限制。
在固定時間內(Hystrix默認是10秒),接口調用出錯比率達到一個閾值(Hystrix默認為50%),會進入熔斷開啟狀態。進入熔斷狀態后, 后續對該服務接口的調用不再經過網絡,直接執行本地的fallback方法。
在進入熔斷開啟狀態一段時間之后(Hystrix默認是5秒),熔斷器會進入半熔斷狀態。所謂半熔斷就是嘗試恢復服務調用,允許有限的流量調用該服務,并監控調用成功率。如果成功率達到預期,則說明服務已恢復,進入熔斷關閉狀態;如果成功率仍舊很低,則重新進入熔斷開啟狀態。
Sentinel
Sentinel 和 Hystrix 的原則是一致的: 當調用鏈路中某個資源出現不穩定,例如,表現為timeout,異常比例升高的時候,則對這個資源的調用進行限制,并讓請求快速失敗,防止避免影響到其它的資源,最終產生雪崩的效果。
Sentinel 熔斷手段:
6.6 服務鏈路追蹤
分布式鏈路追蹤(Distributed Tracing)就是將一次分布式請求還原成調用鏈路。
鏈路跟蹤具備的功能:
故障快速定位
各個調用環節的性能分析
數據分析
生成服務調用拓撲圖
鏈路跟蹤設計原則
設計目標:低侵入、低損耗、拓展性
埋點和生成日志
抓取和存儲日志
分析和統計調用鏈路數據
計算和展示
鏈路跟蹤Trace模型
Trace:一次完整的分布式調用跟蹤鏈路
Span:跟蹤服務調用基本結構,表示跨服務的一次調用; 多span形成樹形結構,組合成一次Trace追蹤記錄
Annotation:
在span中的標注點,記錄整個span時間段內發生的事件:
Cs CLIENT_SEND,客戶端發起請求
Cr CLIENT_RECIEVE,客戶端收到響應
Sr SERVER_RECIEVE,服務端收到請求
Ss SERVER_SEND,服務端發送結果
可以認為是特殊的Annotation,用戶自定義事件:
Event 記錄普通事件
Exception 記錄異常事件
鏈路跟蹤Trace模型
總結
以上是生活随笔為你收集整理的分布式理论,架构设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 能卷死同行的收银系统源码--连锁门店/美
- 下一篇: 我的日程安排表 II