Java面試題 -高併發、高可用、分佈式

1. ⾼併發原則

⽆狀態:

  • ⽆狀態應⽤,便於⽔平擴展
  • 有狀態配置可通過配置中⼼實現⽆狀態
  • 實踐: Disconf、Yaconf、Zookpeer、Consul、Confd、Diamond、Xdiamond等

拆分:

  • 系統維度:按照系統功能、業務拆分,如購物⻋,結算,訂單等
  • 功能維度:對系統功能在做細粒度拆分
  • 讀寫維度:根據讀寫⽐例特徵拆分;讀多,可考慮多級緩存;寫多,可考慮分庫分表
  • AOP維度: 根據訪問特徵,按照AOP進⾏拆分,⽐如商品⻚可分爲CDN、⻚⾯渲染系統,CDN就是⼀個AOP系統
  • 模塊維度:對整體代碼結構劃分Web、Service、DAO

服務化:

  • 服務化演進: 進程內服務-單機遠程服務-集羣⼿動註冊服務-⾃動註冊和發現服務-服務的分組、隔離、路由-服務治理
  • 考慮服務分組、隔離、限流、⿊⽩名單、超時、重試機制、路由、故障補償等
  • 實踐:利⽤Nginx、HaProxy、LVS等實現負載均衡,ZooKeeper、Consul等實現⾃動註冊和發現服務。

消息隊列:

  • ⽬的: 服務解耦(⼀對多消費)、異步處理、流量削峯緩衝等
  • ⼤流量緩衝: 犧牲強⼀致性,保證最終⼀致性(案例:庫存扣減,現在Redis中做扣減,記錄扣減⽇志,通過後臺進程將扣減⽇志應⽤到DB)
  • 數據校對: 解決異步消息機制下消息丟失問題

數據異構:

  • 數據異構: 通過消息隊列機制接收數據變更,原⼦化存儲
  • 數據閉環: 屏蔽多從數據來源,將數據異構存儲,形成閉環

緩存銀彈:

  • ⽤戶層:DNS緩存、瀏覽器DNS緩存、操作系統DNS緩存、本地DNS服務商緩存、DNS服務器緩存、客戶端緩存、瀏覽器緩存(Expires、Cache-Control、Last-Modified、Etag)* App
    客戶緩存(js/css/image…)
  • 代理層:CDN緩存(⼀般基於ATS、Varnish、Nginx、Squid等構建,邊緣節點-
    ⼆級節點-中⼼節點-源站)
  • 接⼊層(Nginx爲例):Proxy_cache: 代理緩存,可以存儲到/dev/shm或者SSD
    FastCGI Cache、Nginx+Lua+Redis: 業務數據緩存
  • 應⽤層:⻚⾯靜態化、業務數據緩存(Redis/Memcached/本地⽂件等)、消息隊列
  • 數據層:NoSQL: Redis、Memcache、SSDB等、MySQL: Innodb/MyISAM等Query Cache、Key Cache、Innodb、Buffer Size等
  • 系統層:CPU : L1/L2/L3 Cache/NUMA、內存、磁盤:磁盤本身緩存dirty_ratio/dirty_background_ratio、陣列卡本身緩存

2. ⾼可⽤原則

降級:

  • 降級開關集中化管理:將開關配置信息推送到各個應⽤
  • 可降級的多級讀服務:如服務調⽤降級爲只讀本地緩存
  • 開關前置化:如Nginx+lua(OpenResty)配置降級策略,引流流量;可基於此做灰度策略
  • 業務降級:⾼併發下,保證核⼼功能,次要功能可由同步改爲異步策略或屏蔽功能

限流:

  • ⽬的: 防⽌惡意請求攻擊或超出系統峯值
  • 實踐:惡意請求流量只訪問到Cache、穿透後端應⽤的流量使⽤Nginx的limit處理、惡意IP使⽤Nginx Deny策略或者iptables拒絕

切流量

  • ⽬的:屏蔽故障機器
  • 實踐:DNS: 更改域名解析⼊⼝,如DNSPOD可以添加備⽤IP,正常IP故障時,會⾃主切換到備⽤地址;⽣效實踐較慢、HttpDNS: 爲了繞過運營商LocalDNS實現的精準流量調度LVS/HaProxy/Nginx: 摘除故障節點

可回滾:

  • 發佈版本失敗時可隨時快速回退到上⼀個穩定版本

3. 業務設計原則

  • 防重設計
  • 冪等設計
  • 流程定義
  • 狀態與狀態機
  • 後臺系統操作可反饋
  • 後臺系統審批化
  • ⽂檔註釋
  • 備份

4. 分佈式與集羣的區別

分佈式是指將不同的業務分佈在不同的地⽅。 ⽽集羣指的是將⼏臺服務器集中在⼀起,實現同⼀業務。

5.分佈式事務

⼆階段提交:

  • 概念:參與者將操作成敗通知協調者,再由協調者根據所有參與者的反饋情報決定各參與者是否要提交操作還是中⽌操作。
  • 作⽤:主要保證了分佈式事務的原⼦性;第⼀階段爲準備階段,第⼆階段爲提交階段;

在這裏插入圖片描述

  • 缺點:不僅要鎖住參與者的所有資源,⽽且要鎖住協調者資源,開銷⼤。⼀句話總結就是:2PC效率很低,對⾼併發很不友好。

三階段提交:

  • 概念:三階段提交協議在協調者和參與者中都引⼊超時機制,並且把兩階段提交協議的第⼀個階段拆分成了兩步:詢問,然後再鎖資源,最後真正提交。這樣三階段提交就有CanCommit、PreCommit、DoCommit三個階段。在這裏插入圖片描述
  • 缺點:如果進⼊PreCommit後,Coordinator發出的是abort請求,假設只有⼀個Cohort收到並進⾏了abort操作,⽽其他對於系統狀態未知的Cohort會根據3PC選擇繼續Commit,此時系統狀態發⽣不⼀致性。

柔性事務:

  • 概念:所謂柔性事務是相對強制鎖表的剛性事務⽽⾔。流程⼊下:服務器A的事務如果執⾏順利,那麼事務A就先⾏提交,如果事務B也執⾏順利,則事務B也提交,整個事務就算完成。但是如果事務B執⾏失敗,事務B本身回滾,這時事務A已經被提交,所以需要執⾏⼀個補償操作,將已經提交的事務A執⾏的操作作反操作,恢復到未執⾏前事務A的狀態。
  • 缺點:業務侵⼊性太強,還要補償操作,缺乏普遍性,沒法⼤規模推⼴。

消息最終⼀致性解決⽅案之RabbitMQ實現:

實現:發送⽅確認+消息持久化+消費者確認。

7. 什麼時候⽤到分佈式開發

優點:

  • i. 模塊解耦:把模塊拆分,使⽤接⼝通信,降低模塊之間的耦合度.
  • ii. 項⽬拆分,不同團隊負責不同的⼦項⽬:把項⽬拆分成若⼲個⼦項⽬,不同的團隊負責不同的⼦項⽬.
  • iii. 提⾼項⽬擴展性:增加功能時只需要再增加⼀個⼦項⽬,調⽤其他系統的接⼝就可以。
  • iv. 分佈式部署:可以靈活的進⾏分佈式部署.
  • v. 提⾼代碼的復⽤性:⽐如service層,如果不採⽤分佈式rest服務⽅式架構就會在⼿機wap商城,微信商城,pc,android,ios每個端都要寫⼀個service層邏輯,開發量⼤,難以維護⼀起升級,這時候就可以採⽤分佈式rest服務⽅式,公⽤⼀個service層。

缺點:

  • i. 系統之間的交互要使⽤遠程通信,接⼝開發增⼤⼯作量;
  • ii. ⽹絡請求有延時;
  • iii. 事務處理⽐較麻煩,需要使⽤分佈式事務。

8. cdn(異地多活)

異地多活:異地多活指分佈在異地的多個站點同時對外提供服務的業務場景。異地多活是⾼可⽤架構設計的⼀種,與傳統的災備設計的最主要區別在於“多活”,即所有站點都是同時在對外提供服務的。

兩地容災切換⽅案:容災是異地多活中最核⼼的⼀環, 以兩個城市異地多活部署架構圖爲例。
在這裏插入圖片描述
在兩個城市(城市1位於華南1地域、城市2位於華東1地域)均部署⼀套完整的業務系統。
下單業務按照“user_id”% 100 進⾏分⽚,在正常情況下:

  • [00~49]分⽚所有的讀寫都在城市1的數據庫實例主庫。
  • [50~99]分⽚所有的讀寫都在城市2的數據庫實例主庫。
    “城市1的數據庫實例主庫”和 “城市2的數據庫實例主庫”建⽴DTS雙向複製。

當出現異常時,需要進⾏容災切換。可能出現的場景有以下4種:
在這裏插入圖片描述
將第2種、第3種異常情況,全部採⽤第2種⽅案進⾏處理,那麼不管是所有的APP Server異常、所有的數據庫異常、整個城市異常,就直接按照城市級容災⽅案處理,直接將APP Server、數據庫切換到到另⼀個城市。

多城異地多活

  • 多城市異地多活模式指的是3個或者3個以上城市間部署異地多活。該模式下存在中⼼節點和單元節點:
  • 在這裏插入圖片描述
  • 中⼼節點:指單元節點的增量數據都需要實時的同步到中⼼節點,同時中⼼節點將所有分⽚的增量數據同步到其他單元節點。
  • 單元節點:即對應分⽚讀寫的節點,該節點需要將該分⽚的增量同步到中⼼節點,並且接收來⾃於中⼼節點的其他分⽚的增量數據。

下圖是3城市異地多活架構圖,其中華東1就是中⼼節點,華南1和華北1是單元節點。

9. 分佈式環境下宕機的處理⽅案?

  • dubbo:服務器宕機,zk臨時被刪除;
  • springcloud:每30s發送⼼跳檢測重新進⾏租約,如果客戶端不能多次更新租約,它將在90s內從服務器註冊中⼼移除。
  • apm監控
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章