分布式理論
1. 說說CAP原則?
CAP原則又稱CAP定理,指的是在一個分布式系統中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區容錯性)這3個基本需求,最多只能同時滿足其中的2個。
CAP原則
選項 | 描述 |
---|---|
Consistency(一致性) | 指數據在多個副本之間能夠保持一致的特性(嚴格的一致性) |
Availability(可用性) | 指系統提供的服務必須一直處于可用的狀態,每次請求都能獲取到非錯的響應(不保證獲取的數據為最新數據) |
Partition tolerance(分區容錯性) | 分布式系統在遇到任何網絡分區故障的時候,仍然能夠對外提供滿足一致性和可用性的服務,除非整個網絡環境都發生了故障 |
2. 為什么CAP不可兼得呢?
首先對于分布式系統,分區是必然存在的,所謂分區指的是分布式系統可能出現的字區域網絡不通,成為孤立區域的的情況。
分區
那么分區容錯性(P)就必須要滿足,因為如果要犧牲分區容錯性,就得把服務和資源放到一個機器,或者一個“同生共死”的集群,那就違背了分布式的初衷。那么滿足分區容錯的基礎上,能不能同時滿足一致性和可用性?假如現在有兩個分區N1和N2,N1和N2分別有不同的分區存儲D1和D2,以及不同的服務S1和S2。
在滿足一致性 的時候,N1和N2的數據要求值一樣的,D1=D2。
在滿足可用性的時候,無論訪問N1還是N2,都能獲取及時的響應。
分區的服務
假如現在有這樣的場景:
用戶訪問了N1,修改了D1的數據。
用戶再次訪問,請求落在了N2。此時D1和D2的數據不一致。
接下來:
保證一致性:此時D1和D2數據不一致,要保證一致性就不能返回不一致的數據,可用性無法保證。
保證可用性:立即響應,可用性得到了保證,但是此時響應的數據和D1不一致,一致性無法保證。
所以,可以看出,分區容錯的前提下,一致性和可用性是矛盾的。
3. CAP對應的模型和應用?
CA without P理論上放棄P(分區容錯性),則C(強一致性)和A(可用性)是可以保證的。實際上分區是不可避免的,嚴格上CA指的是允許分區后各子系統依然保持CA。CA模型的常見應用:
集群數據庫
xFS文件系統
CP without A放棄A(可用),相當于每個請求都需要在Server之間強一致,而P(分區)會導致同步時間無限延長,如此CP也是可以保證的。很多傳統的數據庫分布式事務都屬于這種模式。CP模型的常見應用:
分布式數據庫
分布式鎖
AP wihtout C要高可用并允許分區,則需放棄一致性。一旦分區發生,節點之間可能會失去聯系,為了高可用,每個節點只能用本地數據提供服務,而這樣會導致全局數據的不一致性。現在眾多的NoSQL都屬于此類。AP模型常見應用:
Web緩存
DNS
舉個大家更熟悉的例子,像我們熟悉的注冊中心ZooKeeper、Eureka、Nacos中:
ZooKeeper 保證的是 CP
Eureka 保證的則是 AP
Nacos 不僅支持 CP 也支持 AP
4. BASE理論了解嗎?
BASE(Basically Available、Soft state、Eventual consistency)是基于CAP理論逐步演化而來的,核心思想是即便不能達到強一致性(Strong consistency),也可以根據應用特點采用適當的方式來達到最終一致性(Eventual consistency)的效果。
BASE的主要含義:
Basically Available(基本可用)
什么是基本可用呢?假設系統出現了不可預知的故障,但還是能用,只是相比較正常的系統而言,可能會有響應時間上的損失,或者功能上的降級。
Soft State(軟狀態)
什么是硬狀態呢?要求多個節點的數據副本都是一致的,這是一種“硬狀態”。軟狀態也稱為弱狀態,相比較硬狀態而言,允許系統中的數據存在中間狀態,并認為該狀態不影響系統的整體可用性,即允許系統在多個不同節點的數據副本存在數據延時。
Eventually Consistent(最終一致性)
上面說了軟狀態,但是不應該一直都是軟狀態。在一定時間后,應該到達一個最終的狀態,保證所有副本保持數據一致性,從而達到數據的最終一致性。這個時間取決于網絡延時、系統負載、數據復制方案設計等等因素。
分布式鎖
單體時代,可以直接用本地鎖來實現對競爭資源的加鎖,分布式環境下就要用到分布式鎖了。
5. 有哪些分布式鎖的實現方案呢?
常見的分布式鎖實現方案有三種:MySQL分布式鎖、ZooKepper分布式鎖、Redis分布式鎖。
分布式鎖
5.1 MySQL分布式鎖如何實現呢?
用數據庫實現分布式鎖比較簡單,就是創建一張鎖表,數據庫對字段作唯一性約束。加鎖的時候,在鎖表中增加一條記錄即可;釋放鎖的時候刪除記錄就行。如果有并發請求同時提交到數據庫,數據庫會保證只有一個請求能夠得到鎖。這種屬于數據庫 IO 操作,效率不高,而且頻繁操作會增大數據庫的開銷,因此這種方式在高并發、高性能的場景中用的不多。
5.2 ZooKeeper如何實現分布式鎖?
ZooKeeper也是常見分布式鎖實現方法。ZooKeeper的數據節點和文件目錄類似,例如有一個lock節點,在此節點下建立子節點是可以保證先后順序的,即便是兩個進程同時申請新建節點,也會按照先后順序建立兩個節點。
ZooKeeper如何實現分布式鎖
所以我們可以用此特性實現分布式鎖。以某個資源為目錄,然后這個目錄下面的節點就是我們需要獲取鎖的客戶端,每個服務在目錄下創建節點,如果它的節點,序號在目錄下最小,那么就獲取到鎖,否則等待。釋放鎖,就是刪除服務創建的節點。ZK實際上是一個比較重的分布式組件,實際上應用沒那么多了,所以用ZK實現分布式鎖,其實相對也比較少。
5.3 Redis怎么實現分布式鎖?
Redis實現分布式鎖,是當前應用最廣泛的分布式鎖實現方式。Redis執行命令是單線程的,Redis實現分布式鎖就是利用這個特性。實現分布式鎖最簡單的一個命令:setNx(set if not exist),如果不存在則更新:
setNx?resourceName?value??
加鎖了之后如果機器宕機,那我這個鎖就無法釋放,所以需要加入過期時間,而且過期時間需要和setNx同一個原子操作,在Redis2.8之前需要用lua腳本,但是redis2.8之后redis支持nx和ex操作是同一原子操作。
Redission
當然,一般生產中都是使用Redission客戶端,非常良好地封裝了分布式鎖的api,而且支持RedLock。
分布式事務
6.什么是分布式事務?
分布式事務是相對本地事務而言的,對于本地事務,利用數據庫本身的事務機制,就可以保證事務的ACID特性。
ACID
而在分布式環境下,會涉及到多個數據庫。
多數據庫
分布式事務其實就是將對同一庫事務的概念擴大到了對多個庫的事務。目的是為了保證分布式系統中的數據一致性。分布式事務處理的關鍵是:
需要記錄事務在任何節點所做的所有動作;
事務進行的所有操作要么全部提交,要么全部回滾。
7.分布式事務有哪些常見的實現方案?
分布式常見的實現方案有 2PC、3PC、TCC、本地消息表、MQ消息事務、最大努力通知、SAGA事務 等等。
7.1 說說2PC兩階段提交?
說到2PC,就不得先說分布式事務中的 XA 協議。在這個協議里,有三個角色:
AP(Application):應用系統(服務)
TM(Transaction Manager):事務管理器(全局事務管理)
RM(Resource Manager):資源管理器(數據庫)
XA協議
XA協議采用兩階段提交方式來管理分布式事務。XA接口提供資源管理器與事務管理器之間進行通信的標準接口。兩階段提交的思路可以概括為:參與者將操作成敗通知協調者,再由協調者根據所有參與者的反饋情況決定各參與者是否要提交操作還是回滾操作。
2PC
準備階段:事務管理器要求每個涉及到事務的數據庫預提交(precommit)此操作,并反映是否可以提交
提交階段:事務協調器要求每個數據庫提交數據,或者回滾數據。
優點:盡量保證了數據的強一致,實現成本較低,在各大主流數據庫都有自己實現,對于MySQL是從5.5開始支持。缺點:
單點問題:事務管理器在整個流程中扮演的角色很關鍵,如果其宕機,比如在第一階段已經完成,在第二階段正準備提交的時候事務管理器宕機,資源管理器就會一直阻塞,導致數據庫無法使用。
同步阻塞:在準備就緒之后,資源管理器中的資源一直處于阻塞,直到提交完成,釋放資源。
數據不一致:兩階段提交協議雖然為分布式數據強一致性所設計,但仍然存在數據不一致性的可能,比如在第二階段中,假設協調者發出了事務commit的通知,但是因為網絡問題該通知僅被一部分參與者所收到并執行了commit操作,其余的參與者則因為沒有收到通知一直處于阻塞狀態,這時候就產生了數據的不一致性。
7.2 3PC(三階段提交)了解嗎?
三階段提交(3PC)是二階段提交(2PC)的一種改進版本 ,為解決兩階段提交協議的單點故障和同步阻塞問題。三階段提交有這么三個階段:CanCommit,PreCommit,DoCommit三個階段
3PC
CanCommit:準備階段。協調者向參與者發送commit請求,參與者如果可以提交就返回Yes響應,否則返回No響應。
PreCommit:預提交階段。協調者根據參與者在準備階段的響應判斷是否執行事務還是中斷事務,參與者執行完操作之后返回ACK響應,同時開始等待最終指令。
DoCommit:提交階段。協調者根據參與者在準備階段的響應判斷是否執行事務還是中斷事務:
如果所有參與者都返回正確的ACK響應,則提交事務
如果參與者有一個或多個參與者收到錯誤的ACK響應或者超時,則中斷事務
如果參與者無法及時接收到來自協調者的提交或者中斷事務請求時,在等待超時之后,會繼續進行事務提交
可以看出,三階段提交解決的只是兩階段提交中單體故障和同步阻塞的問題,因為加入了超時機制,這里的超時的機制作用于 預提交階段 和 提交階段。如果等待 預提交請求 超時,參與者直接回到準備階段之前。如果等到提交請求超時,那參與者就會提交事務了。無論是2PC還是3PC都不能保證分布式系統中的數據100%一致。
7.3 TCC了解嗎?
TCC(Try Confirm Cancel) ,是兩階段提交的一個變種,針對每個操作,都需要有一個其對應的確認和取消操作,當操作成功時調用確認操作,當操作失敗時調用取消操作,類似于二階段提交,只不過是這里的提交和回滾是針對業務上的,所以基于TCC實現的分布式事務也可以看做是對業務的一種補償機制。
TCC下單減庫存
Try:嘗試待執行的業務。訂單系統將當前訂單狀態設置為支付中,庫存系統校驗當前剩余庫存數量是否大于1,然后將可用庫存數量設置為庫存剩余數量-1,。
Confirm:確認執行業務,如果Try階段執行成功,接著執行Confirm 階段,將訂單狀態修改為支付成功,庫存剩余數量修改為可用庫存數量。
Cancel:取消待執行的業務,如果Try階段執行失敗,執行Cancel 階段,將訂單狀態修改為支付失敗,可用庫存數量修改為庫存剩余數量。
TCC 是業務層面的分布式事務,保證最終一致性,不會一直持有資源的鎖。
優點: 把數據庫層的二階段提交交給應用層來實現,規避了數據庫的 2PC 性能低下問題
缺點:TCC 的 Try、Confirm 和 Cancel 操作功能需業務提供,開發成本高。TCC 對業務的侵入較大和業務緊耦合,需要根據特定的場景和業務邏輯來設計相應的操作
7.4 本地消息表了解嗎?
本地消息表的核心思想是將分布式事務拆分成本地事務進行處理。例如,可以在訂單庫新增一個消息表,將新增訂單和新增消息放到一個事務里完成,然后通過輪詢的方式去查詢消息表,將消息推送到MQ,庫存服務去消費MQ。
本地消息表
執行流程:
訂單服務,添加一條訂單和一條消息,在一個事務里提交
訂單服務,使用定時任務輪詢查詢狀態為未同步的消息表,發送到MQ,如果發送失敗,就重試發送
庫存服務,接收MQ消息,修改庫存表,需要保證冪等操作
如果修改成功,調用rpc接口修改訂單系統消息表的狀態為已完成或者直接刪除這條消息
如果修改失敗,可以不做處理,等待重試
訂單服務中的消息有可能由于業務問題會一直重復發送,所以為了避免這種情況可以記錄一下發送次數,當達到次數限制之后報警,人工接入處理;庫存服務需要保證冪等,避免同一條消息被多次消費造成數據不一致。本地消息表這種方案實現了最終一致性,需要在業務系統里增加消息表,業務邏輯中多一次插入的DB操作,所以性能會有損耗,而且最終一致性的間隔主要有定時任務的間隔時間決定
7.5 MQ消息事務了解嗎?
消息事務的原理是將兩個事務通過消息中間件進行異步解耦。訂單服務執行自己的本地事務,并發送MQ消息,庫存服務接收消息,執行自己的本地事務,乍一看,好像跟本地消息表的實現方案類似,只是省去 了對本地消息表的操作和輪詢發送MQ的操作,但實際上兩種方案的實現是不一樣的。消息事務一定要保證業務操作與消息發送的一致性,如果業務操作成功,這條消息也一定投遞成功。
MQ消息事務
執行流程:
發送prepare消息到消息中間件
發送成功后,執行本地事務
如果事務執行成功,則commit,消息中間件將消息下發至消費端
如果事務執行失敗,則回滾,消息中間件將這條prepare消息刪除
消費端接收到消息進行消費,如果消費失敗,則不斷重試
消息事務依賴于消息中間件的事務消息,例如我們熟悉的RocketMQ就支持事務消息(半消息),也就是只有收到發送方確定才會正常投遞的消息。這種方案也是實現了最終一致性,對比本地消息表實現方案,不需要再建消息表,對性能的損耗和業務的入侵更小。
7.6 最大努力通知了解嗎?
最大努力通知相比實現會簡單一些,適用于一些對最終一致性實時性要求沒那么高的業務,比如支付通知,短信通知。以支付通知為例,業務系統調用支付平臺進行支付,支付平臺進行支付,進行操作支付之后支付平臺會去同步通知業務系統支付操作是否成功,如果不成功,會一直異步重試,但是會有一個最大通知次數,如果超過這個次數后還是通知失敗,就不再通知,業務系統自行調用支付平臺提供一個查詢接口,供業務系統進行查詢支付操作是否成功。
最大努力通知
執行流程:
業務系統調用支付平臺支付接口, 并在本地進行記錄,支付狀態為支付中
支付平臺進行支付操作之后,無論成功還是失敗,同步給業務系統一個結果通知
如果通知一直失敗則根據重試規則異步進行重試,達到最大通知次數后,不再通知
支付平臺提供查詢訂單支付操作結果接口
業務系統根據一定業務規則去支付平臺查詢支付結果
8.你們用什么?能說一下Seata嗎?
我們用比較常用的是Seata——自己去實現分布式事務調度還是比較麻煩的。Seata 的設計目標是對業務無侵入,因此它是從業務無侵入的兩階段提交(全局事務)著手,在傳統的兩階段上進行改進,他把一個分布式事務理解成一個包含了若干分支事務的全局事務。而全局事務的職責是協調它管理的分支事務達成一致性,要么一起成功提交,要么一起失敗回滾。也就是一榮俱榮一損俱損~
全局事務和分支事務
Seata 中存在這么幾種重要角色:
TC(Transaction Coordinator):事務協調者。管理全局的分支事務的狀態,用于全局性事務的提交和回滾。
TM(Transaction Manager):事務管理者。用于開啟、提交或回滾事務。
RM(Resource Manager):資源管理器。用于分支事務上的資源管理,向 TC 注冊分支事務,上報分支事務的狀態,接收 TC 的命令來提交或者回滾分支事務。
Seata工作流程
S'eata整體執行流程:
服務A中的 TM 向 TC 申請開啟一個全局事務,TC 就會創建一個全局事務并返回一個唯一的 XID
服務A中的 RM 向 TC 注冊分支事務,然后將這個分支事務納入 XID 對應的全局事務管轄中
服務A開始執行分支事務
服務A開始遠程調用B服務,此時 XID 會根據調用鏈傳播
服務B中的 RM 也向 TC 注冊分支事務,然后將這個分支事務納入 XID 對應的全局事務管轄中
服務B開始執行分支事務
全局事務調用處理結束后,TM 會根據有誤異常情況,向 TC 發起全局事務的提交或回滾
TC 協調其管轄之下的所有分支事務,決定是提交還是回滾
分布式一致性算法
9.分布式算法paxos了解么 ?
Paxos 有點類似前面說的 2PC,3PC,但比這兩種算法更加完善。在很多多大廠都得到了工程實踐,比如阿里的 OceanBase 的 分布式數據庫, Google 的 chubby 分布式鎖 。
Paxos算法是什么?
Paxos 算法是 基于消息傳遞 且具有 高效容錯特性 的一致性算法,目前公認的解決 分布式一致性問題 最有效的算法之一。
Paxos算法的工作流程?
角色
在Paxos中有這么幾個角色:
Proposer(提議者) : 提議者提出提案,用于投票表決。
Accecptor(接受者) : 對提案進行投票,并接受達成共識的提案。
Learner(學習者) : 被告知投票的結果,接受達成共識的提案。
在實際中,一個節點可以同時充當不同角色。
Paxos的三種角色
提議者提出提案,提案=編號+value,可以表示為[M,V],每個提案都有唯一編號,而且編號的大小是趨勢遞增的。
算法流程
Paxos算法包含兩個階段,第一階段**Prepare(準備)、第二階段Accept(接受)**。
Paxos算法流程
Prepare(準備)階段
提議者提議一個新的提案 P[Mn,?],然后向接受者的某個超過半數的子集成員發送編號為Mn的準備請求
如果一個接受者收到一個編號為Mn的準備請求,并且編號Mn大于它已經響應的所有準備請求的編號,那么它就會將它已經批準過的最大編號的提案作為響應反饋給提議者,同時該接受者會承諾不會再批準任何編號小于Mn的提案。
總結一下,接受者在收到提案后,會給與提議者兩個承諾與一個應答:
兩個承諾:
承諾不會再接受提案號小于或等于 Mn 的 Prepare 請求
承諾不會再接受提案號小于Mn 的 Accept 請求
一個應答:
不違背以前作出的承諾的前提下,回復已經通過的提案中提案號最大的那個提案所設定的值和提案號Mmax,如果這個值從來沒有被任何提案設定過,則返回空值。如果不滿足已經做出的承諾,即收到的提案號并不是決策節點收到過的最大的,那允許直接對此 Prepare 請求不予理會。
Accept(接受)階段
如果提議者收到來自半數以上的接受者對于它發出的編號為Mn的準備請求的響應,那么它就會發送一個針對[Mn,Vn]的接受請求給接受者,注意Vn的值就是收到的響應中編號最大的提案的值,如果響應中不包含任何提案,那么它可以隨意選定一個值。
如果接受者收到這個針對[Mn,Vn]提案的接受請求,只要該接受者尚未對編號大于Mn的準備請求做出響應,它就可以通過這個提案。
當提議者收到了多數接受者的接受應答后,協商結束,共識決議形成,將形成的決議發送給所有學習節點進行學習。所以Paxos算法的整體詳細流程如下:
Paxos詳細流程
算法的流程模擬,可以查看參考[13]。
Paxos算法有什么缺點嗎?怎么優化?
前面描述的可以稱之為Basic Paxos 算法,在單提議者的前提下是沒有問題的,但是假如有多個提議者互不相讓,那么就可能導致整個提議的過程進入了死循環。Lamport 提出了 Multi Paxos 的算法思想。Multi Paxos算法思想,簡單說就是在多個提議者的情況下,選出一個Leader(領導者),由領導者作為唯一的提議者,這樣就可以解決提議者沖突的問題。
10.說說Raft算法?
Raft算法是什么?
Raft 也是一個 一致性算法,和 Paxos 目標相同。但它還有另一個名字 - 易于理解的一致性算法。Paxos 和 Raft 都是為了實現 一致性 產生的。這個過程如同選舉一樣,參選者 需要說服 大多數選民 (Server) 投票給他,一旦選定后就跟隨其操作。Paxos 和 Raft 的區別在于選舉的 具體過程 不同。
Raft算法的工作流程?
Raft算法的角色
Raft 協議將 Server 進程分為三種角色:
Leader(領導者)
Follower(跟隨者)
Candidate(候選人)
就像一個民主社會,領導者由跟隨者投票選出。剛開始沒有 領導者,所有集群中的 參與者 都是 跟隨者。那么首先開啟一輪大選。在大選期間 所有跟隨者 都能參與競選,這時所有跟隨者的角色就變成了 候選人,民主投票選出領袖后就開始了這屆領袖的任期,然后選舉結束,所有除 領導者 的 候選人 又變回 跟隨者 服從領導者領導。這里提到一個概念 「任期」,用術語 Term 表達。三類角色的變遷圖如下:
Raft三種角色變遷圖
Leader選舉過程
Raft 使用心跳(heartbeat)觸發Leader選舉。當Server啟動時,初始化為Follower。Leader向所有Followers周期性發送heartbeat。如果Follower在選舉超時時間內沒有收到Leader的heartbeat,就會等待一段隨機的時間后發起一次Leader選舉。Follower將其當前term加一然后轉換為Candidate。它首先給自己投票并且給集群中的其他服務器發送 RequestVote RPC 。結果有以下三種情況:
贏得了多數(超過1/2)的選票,成功選舉為Leader;
收到了Leader的消息,表示有其它服務器已經搶先當選了Leader;
沒有Server贏得多數的選票,Leader選舉失敗,等待選舉時間超時(Election Timeout)后發起下一次選舉。
Leader選舉
選出 Leader 后,Leader 通過 定期 向所有 Follower 發送 心跳信息 維持其統治。若 Follower 一段時間未收到 Leader 的 心跳,則認為 Leader 可能已經掛了,然后再次發起 選舉 過程。
分布式設計
11.說說什么是冪等性?
什么是冪等性?
冪等性是一個數學概念,用在接口上:用在接口上就可以理解為:同一個接口,多次發出同一個請求,請求的結果是一致的。簡單說,就是多次調用如一次。
什么是冪等性問題?
在系統的運行中,可能會出現這樣的問題:
用戶在填寫某些form表單時,保存按鈕不小心快速點了兩次,表中竟然產生了兩條重復的數據,只是id不一樣。
開發人員在項目中為了解決接口超時問題,通常會引入了重試機制。第一次請求接口超時了,請求方沒能及時獲取返回結果(此時有可能已經成功了),于是會對該請求重試幾次,這樣也會產生重復的數據。
mq消費者在讀取消息時,有時候會讀取到重復消息,也會產生重復的數據。
這些都是常見的冪等性問題。在分布式系統里,只要下游服務有寫(保存、更新)的操作,都有可能會產生冪等性問題。PS:冪等和防重有些不同,防重強調的防止數據重復,冪等強調的是多次調用如一次,防重包含冪等。
怎么保證接口冪等性?
接口冪等性
insert前先select在保存數據的接口中,在insert前,先根據requestId等字段先select一下數據。如果該數據已存在,則直接返回,如果不存在,才執行 ?insert操作。
加唯一索引加唯一索引是個非常簡單但很有效的辦法,如果重復插入數據的話,就會拋出異常,為了保證冪等性,一般需要捕獲這個異常。如果是java程序需要捕獲:DuplicateKeyException異常,如果使用了spring框架還需要捕獲:MySQLIntegrityConstraintViolationException異常。
加悲觀鎖更新邏輯,比如更新用戶賬戶余額,可以加悲觀鎖,把對應用戶的哪一行數據鎖住。同一時刻只允許一個請求獲得鎖,其他請求則等待。
?
?
????select?*?from?user?id=123?for?update;??
這種方式有一個缺點,獲取不到鎖的請求一般只能報失敗,比較難保證接口返回相同值。
?
?
加樂觀鎖更新邏輯,也可以用樂觀鎖,性能更好。可以在表中增加一個timestamp或者version字段,例如version:在更新前,先查詢一下數據,將version也作為更新的條件,同時也更新version:
?
?
update?user?set?amount=amount+100,version=version+1?where?id=123?and?version=1;??
更新成功后,version增加,重復更新請求進來就無法更新了。
?
?
建防重表有時候表中并非所有的場景都不允許產生重復的數據,只有某些特定場景才不允許。這時候,就可以使用防重表的方式。例如消息消費中,創建防重表,存儲消息的唯一ID,消費時先去查詢是否已經消費,已經消費直接返回成功。
狀態機有些業務表是有狀態的,比如訂單表中有:1-下單、2-已支付、3-完成、4-撤銷等狀態,可以通過限制狀態的流動來完成冪等。
分布式鎖直接在數據庫上加鎖的做法性能不夠友好,可以使用分布式鎖的方式,目前最流行的分布式鎖實現是通過Redis,具體實現一般都是使用Redission框架。
token機制請求接口之前,需要先獲取一個唯一的token,再帶著這個token去完成業務操作,服務端根據這個token是否存在,來判斷是否是重復的請求。
分布式限流
12.你了解哪些限流算法?
計數器
計數器比較簡單粗暴,比如我們要限制1s能夠通過的請求數,實現的思路就是從第一個請求進來開始計時,在接下來的1s內,每個請求進來請求數就+1,超過最大請求數的請求會被拒絕,等到1s結束后計數清零,重新開始計數。這種方式有個很大的弊端:比如前10ms已經通過了最大的請求數,那么后面的990ms的請求只能拒絕,這種現象叫做“突刺現象”。
漏桶算法
就是桶底出水的速度恒定,進水的速度可能快慢不一,但是當進水量大于出水量的時候,水會被裝在桶里,不會直接被丟棄;但是桶也是有容量限制的,當桶裝滿水后溢出的部分還是會被丟棄的。算法實現:可以準備一個隊列來保存暫時處理不了的請求,然后通過一個線程池定期從隊列中獲取請求來執行。
漏桶算法
令牌桶算法
令牌桶就是生產訪問令牌的一個地方,生產的速度恒定,用戶訪問的時候當桶中有令牌時就可以訪問,否則將觸發限流。實現方案:Guava RateLimiter限流Guava RateLimiter是一個谷歌提供的限流,其基于令牌桶算法,比較適用于單實例的系統。
令牌桶算法
分布式面試題就整理到這里了,主要是偏理論的一些問題,分布式其實是個很大的類型
編輯:黃飛
?
評論
查看更多