面試官問分佈式技術面試題,一臉懵逼怎麼辦?

1. 分佈式緩存

1.1. Redis 有什麼數據類型?分別用於什麼場景?

數據類型 能夠存儲的值 操做
STRING 字符串、整數或者浮點數 對整個字符串或者字符串的其中一部分執行操做
對整數和浮點數執行自增或者自減操做
LIST 列表 從兩端壓入或者彈出元素
讀取單個或者多個元素
進行修剪,只保留一個範圍內的元素
SET 無序集合 添加、獲取、移除單個元素
檢查一個元素是否存在於集合中
計算交集、並集、差集
從集合裏面隨機獲取元素
HASH 包含鍵值對的無序散列表 添加、獲取、移除單個鍵值對
獲取全部鍵值對
檢查某個鍵是否存在
ZSET 有序集合 添加、獲取、刪除元素
根據分值範圍或者成員來獲取元素
計算一個鍵的排名

What Redis data structures look like前端

1.2. Redis 的主從複製是如何實現的?

  1. 從服務器鏈接主服務器,發送 SYNC 命令;
  2. 主服務器接收到 SYNC 命名後,開始執行 BGSAVE 命令生成 RDB 文件並使用緩衝區記錄此後執行的全部寫命令;
  3. 主服務器 BGSAVE 執行完後,向全部從服務器發送快照文件,並在發送期間繼續記錄被執行的寫命令;
  4. 從服務器收到快照文件後丟棄全部舊數據,載入收到的快照;
  5. 主服務器快照發送完畢後開始向從服務器發送緩衝區中的寫命令;
  6. 從服務器完成對快照的載入,開始接收命令請求,並執行來自主服務器緩衝區的寫命令;

 

1.3. Redis 的 key 是如何尋址的?

背景

(1)redis 中的每個數據庫,都由一個 redisDb 的結構存儲。其中:java

  • redisDb.id 存儲着 redis 數據庫以整數表示的號碼。
  • redisDb.dict 存儲着該庫全部的鍵值對數據。
  • redisDb.expires 保存着每個鍵的過時時間。

(2)當 redis 服務器初始化時,會預先分配 16 個數據庫(該數量能夠經過配置文件配置),全部數據庫保存到結構 redisServer 的一個成員 redisServer.db 數組中。當咱們選擇數據庫 select number 時,程序直接經過 redisServer.db[number] 來切換數據庫。有時候當程序須要知道本身是在哪一個數據庫時,直接讀取 redisDb.id 便可。node

(3)redis 的字典使用哈希表做爲其底層實現。dict 類型使用的兩個指向哈希表的指針,其中 0 號哈希表(ht[0])主要用於存儲數據庫的全部鍵值,而 1 號哈希表主要用於程序對 0 號哈希表進行 rehash 時使用,rehash 通常是在添加新值時會觸發,這裏不作過多的贅述。因此 redis 中查找一個 key,其實就是對進行該 dict 結構中的 ht[0] 進行查找操做。redis

(4)既然是哈希,那麼咱們知道就會有哈希碰撞,那麼當多個鍵哈希以後爲同一個值怎麼辦呢?redis 採起鏈表的方式來存儲多個哈希碰撞的鍵。也就是說,當根據 key 的哈希值找到該列表後,若是列表的長度大於 1,那麼咱們須要遍歷該鏈表來找到咱們所查找的 key。固然,通常狀況下鏈表長度都爲是 1,因此時間複雜度可看做 o(1)。算法

尋址 key 的步驟

  1. 當拿到一個 key 後,redis 先判斷當前庫的 0 號哈希表是否爲空,即:if (dict->ht[0].size == 0)。若是爲 true 直接返回 NULL。
  2. 判斷該 0 號哈希表是否須要 rehash,由於若是在進行 rehash,那麼兩個表中者有可能存儲該 key。若是正在進行 rehash,將調用一次_dictRehashStep 方法,_dictRehashStep 用於對數據庫字典、以及哈希鍵的字典進行被動 rehash,這裏不做贅述。
  3. 計算哈希表,根據當前字典與 key 進行哈希值的計算。
  4. 根據哈希值與當前字典計算哈希表的索引值。
  5. 根據索引值在哈希表中取出鏈表,遍歷該鏈表找到 key 的位置。通常狀況,該鏈表長度爲 1。
  6. 當 ht[0] 查找完了以後,再進行了次 rehash 判斷,若是未在 rehashing,則直接結束,不然對 ht[1]重複 345 步驟。

 

1.4. Redis 的集羣模式是如何實現的?

Redis Cluster 是 Redis 的分佈式解決方案,在 Redis 3.0 版本正式推出的。數據庫

Redis Cluster 去中心化,每一個節點保存數據和整個集羣狀態,每一個節點都和其餘全部節點鏈接。json

Redis Cluster 節點分配

Redis Cluster 特色:數組

  1. 全部的 redis 節點彼此互聯(PING-PONG 機制),內部使用二進制協議優化傳輸速度和帶寬。
  2. 節點的 fail 是經過集羣中超過半數的節點檢測失效時才生效。
  3. 客戶端與 redis 節點直連,不須要中間 proxy 層。客戶端不須要鏈接集羣全部節點,鏈接集羣中任何一個可用節點便可。
  4. redis-cluster 把全部的物理節點映射到[0-16383] 哈希槽 (hash slot)上(不必定是平均分配),cluster 負責維護 node、slot、value。
  5. Redis 集羣預分好 16384 個桶,當須要在 Redis 集羣中放置一個 key-value 時,根據 CRC16(key) mod 16384 的值,決定將一個 key 放到哪一個桶中。

Redis Cluster 主從模式

Redis Cluster 爲了保證數據的高可用性,加入了主從模式。緩存

一個主節點對應一個或多個從節點,主節點提供數據存取,從節點則是從主節點拉取數據備份。當這個主節點掛掉後,就會有這個從節點選取一個來充當主節點,從而保證集羣不會掛掉。因此,在集羣創建的時候,必定要爲每一個主節點都添加了從節點。安全

Redis Sentinel

Redis Sentinel 用於管理多個 Redis 服務器,它有三個功能:

  • 監控(Monitoring) - Sentinel 會不斷地檢查你的主服務器和從服務器是否運做正常。
  • 提醒(Notification) - 當被監控的某個 Redis 服務器出現問題時, Sentinel 能夠經過 API 向管理員或者其餘應用程序發送通知。
  • 自動故障遷移(Automatic failover) - 當一個主服務器不能正常工做時, Sentinel 會開始一次自動故障遷移操做, 它會將失效主服務器的其中一個從服務器升級爲新的主服務器, 並讓失效主服務器的其餘從服務器改成複製新的主服務器; 當客戶端試圖鏈接失效的主服務器時, 集羣也會向客戶端返回新主服務器的地址, 使得集羣可使用新主服務器代替失效服務器。

Redis 集羣中應該有奇數個節點,因此至少有三個節點。

哨兵監控集羣中的主服務器出現故障時,須要根據 quorum 選舉出一個哨兵來執行故障轉移。選舉須要 majority,即大多數哨兵是運行的(2 個哨兵的 majority=2,3 個哨兵的 majority=2,5 個哨兵的 majority=3,4 個哨兵的 majority=2)。

假設集羣僅僅部署 2 個節點

+----+         +----+
| M1 |---------| R1 |
| S1 |         | S2 |
+----+         +----+

若是 M1 和 S1 所在服務器宕機,則哨兵只有 1 個,沒法知足 majority 來進行選舉,就不能執行故障轉移。

 

1.5. Redis 如何實現分佈式鎖?ZooKeeper 如何實現分佈式鎖?比較兩者優劣?

分佈式鎖的三種實現:

  • 基於數據庫實現分佈式鎖;
  • 基於緩存(Redis 等)實現分佈式鎖;
  • 基於 Zookeeper 實現分佈式鎖;

數據庫實現

Redis 實現

  1. 獲取鎖的時候,使用 setnx 加鎖,並使用 expire 命令爲鎖添加一個超時時間,超過該時間則自動釋放鎖,鎖的 value 值爲一個隨機生成的 UUID,經過此在釋放鎖的時候進行判斷。
  2. 獲取鎖的時候還設置一個獲取的超時時間,若超過這個時間則放棄獲取鎖。
  3. 釋放鎖的時候,經過 UUID 判斷是否是該鎖,如果該鎖,則執行 delete 進行鎖釋放。

 

ZooKeeper 實現

  1. 建立一個目錄 mylock;
  2. 線程 A 想獲取鎖就在 mylock 目錄下建立臨時順序節點;
  3. 獲取 mylock 目錄下全部的子節點,而後獲取比本身小的兄弟節點,若是不存在,則說明當前線程順序號最小,得到鎖;
  4. 線程 B 獲取全部節點,判斷本身不是最小節點,設置監聽比本身次小的節點;
  5. 線程 A 處理完,刪除本身的節點,線程 B 監聽到變動事件,判斷本身是否是最小的節點,若是是則得到鎖。

實現對比

ZooKeeper 具有高可用、可重入、阻塞鎖特性,可解決失效死鎖問題。 但 ZooKeeper 由於須要頻繁的建立和刪除節點,性能上不如 Redis 方式。

1.6. Redis 的持久化方式?有什麼優缺點?持久化實現原理?

RDB 快照(snapshot)

將存在於某一時刻的全部數據都寫入到硬盤中。

快照的原理

在默認狀況下,Redis 將數據庫快照保存在名字爲 dump.rdb 的二進制文件中。你能夠對 Redis 進行設置, 讓它在「N 秒內數據集至少有 M 個改動」這一條件被知足時, 自動保存一次數據集。你也能夠經過調用 SAVE 或者 BGSAVE,手動讓 Redis 進行數據集保存操做。這種持久化方式被稱爲快照。

當 Redis 須要保存 dump.rdb 文件時, 服務器執行如下操做:

  • Redis 建立一個子進程。
  • 子進程將數據集寫入到一個臨時快照文件中。
  • 當子進程完成對新快照文件的寫入時,Redis 用新快照文件替換原來的快照文件,並刪除舊的快照文件。

這種工做方式使得 Redis 能夠從寫時複製(copy-on-write)機制中獲益。

快照的優勢

  • 它保存了某個時間點的數據集,很是適用於數據集的備份。
  • 很方便傳送到另外一個遠端數據中心或者亞馬遜的 S3(可能加密),很是適用於災難恢復。
  • 快照在保存 RDB 文件時父進程惟一須要作的就是 fork 出一個子進程,接下來的工做所有由子進程來作,父進程不須要再作其餘 IO 操做,因此快照持久化方式能夠最大化 redis 的性能。
  • 與 AOF 相比,在恢復大的數據集的時候,DB 方式會更快一些。

快照的缺點

  • 若是你但願在 redis 意外中止工做(例如電源中斷)的狀況下丟失的數據最少的話,那麼快照不適合你。
  • 快照須要常常 fork 子進程來保存數據集到硬盤上。當數據集比較大的時候,fork 的過程是很是耗時的,可能會致使 Redis 在一些毫秒級內不能響應客戶端的請求。

AOF

AOF 持久化方式記錄每次對服務器執行的寫操做。當服務器重啓的時候會從新執行這些命令來恢復原始的數據。

 

AOF 的原理

  • Redis 建立一個子進程。
  • 子進程開始將新 AOF 文件的內容寫入到臨時文件。
  • 對於全部新執行的寫入命令,父進程一邊將它們累積到一個內存緩存中,一邊將這些改動追加到現有 AOF 文件的末尾,這樣樣即便在重寫的中途發生停機,現有的 AOF 文件也仍是安全的。
  • 當子進程完成重寫工做時,它給父進程發送一個信號,父進程在接收到信號以後,將內存緩存中的全部數據追加到新 AOF 文件的末尾。
  • 搞定!如今 Redis 原子地用新文件替換舊文件,以後全部命令都會直接追加到新 AOF 文件的末尾。

 

AOF 的優勢

  • 使用默認的每秒 fsync 策略,Redis 的性能依然很好(fsync 是由後臺線程進行處理的,主線程會盡力處理客戶端請求),一旦出現故障,使用 AOF ,你最多丟失 1 秒的數據。
  • AOF 文件是一個只進行追加的日誌文件,因此不須要寫入 seek,即便因爲某些緣由(磁盤空間已滿,寫的過程當中宕機等等)未執行完整的寫入命令,你也也可以使用 redis-check-aof 工具修復這些問題。
  • Redis 能夠在 AOF 文件體積變得過大時,自動地在後臺對 AOF 進行重寫:重寫後的新 AOF 文件包含了恢復當前數據集所需的最小命令集合。整個重寫操做是絕對安全的。
  • AOF 文件有序地保存了對數據庫執行的全部寫入操做,這些寫入操做以 Redis 協議的格式保存。所以 AOF 文件的內容很是容易被人讀懂,對文件進行分析(parse)也很輕鬆。

 

AOF 的缺點

  • 對於相同的數據集來講,AOF 文件的體積一般要大於 RDB 文件的體積。
  • 根據所使用的 fsync 策略,AOF 的速度可能會慢於快照。在通常狀況下,每秒 fsync 的性能依然很是高,而關閉 fsync 可讓 AOF 的速度和快照同樣快,即便在高負荷之下也是如此。不過在處理巨大的寫入載入時,快照能夠提供更有保證的最大延遲時間(latency)。

 

1.7. Redis 過時策略有哪些?

  • noeviction - 當內存使用達到閾值的時候,全部引發申請內存的命令會報錯。
  • allkeys-lru - 在主鍵空間中,優先移除最近未使用的 key。
  • allkeys-random - 在主鍵空間中,隨機移除某個 key。
  • volatile-lru - 在設置了過時時間的鍵空間中,優先移除最近未使用的 key。
  • volatile-random - 在設置了過時時間的鍵空間中,隨機移除某個 key。
  • volatile-ttl - 在設置了過時時間的鍵空間中,具備更早過時時間的 key 優先移除。

 

1.8. Redis 和 Memcached 有什麼區別?

二者都是非關係型內存鍵值數據庫。有如下主要不一樣:

數據類型

  • Memcached 僅支持字符串類型;
  • 而 Redis 支持五種不一樣種類的數據類型,使得它能夠更靈活地解決問題。

數據持久化

  • Memcached 不支持持久化;
  • Redis 支持兩種持久化策略:RDB 快照和 AOF 日誌。

分佈式

  • Memcached 不支持分佈式,只能經過在客戶端使用像一致性哈希這樣的分佈式算法來實現分佈式存儲,這種方式在存儲和查詢時都須要先在客戶端計算一次數據所在的節點。
  • Redis Cluster 實現了分佈式的支持。

內存管理機制

  • Memcached 將內存分割成特定長度的塊來存儲數據,以徹底解決內存碎片的問題,可是這種方式會使得內存的利用率不高,例如塊的大小爲 128 bytes,只存儲 100 bytes 的數據,那麼剩下的 28 bytes 就浪費掉了。
  • 在 Redis 中,並非全部數據都一直存儲在內存中,能夠將一些好久沒用的 value 交換到磁盤。而 Memcached 的數據則會一直在內存中。

 

1.9. 爲何單線程的 Redis 性能反而優於多線程的 Memcached?

Redis 快速的緣由:

  1. 絕大部分請求是純粹的內存操做(很是快速)
  2. 採用單線程,避免了沒必要要的上下文切換和競爭條件
  3. 非阻塞 IO

內部實現採用 epoll,採用了 epoll+本身實現的簡單的事件框架。epoll 中的讀、寫、關閉、鏈接都轉化成了事件,而後利用 epoll 的多路複用特性,毫不在 io 上浪費一點時間。

2. 分佈式消息隊列(MQ)

2.1. 爲何使用 MQ?

  • 異步處理 - 相比於傳統的串行、並行方式,提升了系統吞吐量。
  • 應用解耦 - 系統間經過消息通訊,不用關心其餘系統的處理。
  • 流量削鋒 - 能夠經過消息隊列長度控制請求量;能夠緩解短期內的高併發請求。
  • 日誌處理 - 解決大量日誌傳輸。
  • 消息通信 - 消息隊列通常都內置了高效的通訊機制,所以也能夠用在純的消息通信。好比實現點對點消息隊列,或者聊天室等。

 

2.2. 如何保證 MQ 的高可用?

數據複製

  1. 將全部 Broker 和待分配的 Partition 排序
  2. 將第 i 個 Partition 分配到第(i mod n)個 Broker 上
  3. 將第 i 個 Partition 的第 j 個 Replica 分配到第((i + j) mode n)個 Broker 上

選舉主服務器

 

2.3. MQ 有哪些常見問題?如何解決這些問題?

MQ 的常見問題有:

  1. 消息的順序問題
  2. 消息的重複問題

消息的順序問題

消息有序指的是能夠按照消息的發送順序來消費。

假如生產者產生了 2 條消息:M一、M2,假定 M1 發送到 S1,M2 發送到 S2,若是要保證 M1 先於 M2 被消費,怎麼作?

 

 

 

解決方案:

(1)保證生產者 - MQServer - 消費者是一對一對一的關係

 

 

 

缺陷:

  • 並行度就會成爲消息系統的瓶頸(吞吐量不夠)
  • 更多的異常處理,好比:只要消費端出現問題,就會致使整個處理流程阻塞,咱們不得不花費更多的精力來解決阻塞的問題。

(2)經過合理的設計或者將問題分解來規避。

  • 不關注亂序的應用實際大量存在
  • 隊列無序並不意味着消息無序

因此從業務層面來保證消息的順序而不只僅是依賴於消息系統,是一種更合理的方式。

消息的重複問題

形成消息重複的根本緣由是:網絡不可達。

因此解決這個問題的辦法就是繞過這個問題。那麼問題就變成了:若是消費端收到兩條同樣的消息,應該怎樣處理?

消費端處理消息的業務邏輯保持冪等性。只要保持冪等性,無論來多少條重複消息,最後處理的結果都同樣。 保證每條消息都有惟一編號且保證消息處理成功與去重表的日誌同時出現。利用一張日誌表來記錄已經處理成功的消息的 ID,若是新到的消息 ID 已經在日誌表中,那麼就再也不處理這條消息。

2.4. Kafka, ActiveMQ, RabbitMQ, RocketMQ 各有什麼優缺點?

 

3. 分佈式服務(RPC)

3.1. Dubbo 的實現過程?

節點角色:

節點 角色說明
Provider 暴露服務的服務提供方
Consumer 調用遠程服務的服務消費方
Registry 服務註冊與發現的註冊中心
Monitor 統計服務的調用次數和調用時間的監控中心
Container 服務運行容器

調用關係:

  1. 務容器負責啓動,加載,運行服務提供者。
  2. 服務提供者在啓動時,向註冊中心註冊本身提供的服務。
  3. 服務消費者在啓動時,向註冊中心訂閱本身所需的服務。
  4. 註冊中心返回服務提供者地址列表給消費者,若是有變動,註冊中心將基於長鏈接推送變動數據給消費者。
  5. 服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一臺提供者進行調用,若是調用失敗,再選另外一臺調用。
  6. 服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鐘發送一次統計數據到監控中心。

 

3.2. Dubbo 負載均衡策略有哪些?

Random

  • 隨機,按權重設置隨機機率。
  • 在一個截面上碰撞的機率高,但調用量越大分佈越均勻,並且按機率使用權重後也比較均勻,有利於動態調整提供者權重。

RoundRobin

  • 輪循,按公約後的權重設置輪循比率。
  • 存在慢的提供者累積請求的問題,好比:第二臺機器很慢,但沒掛,當請求調到第二臺時就卡在那,長此以往,全部請求都卡在調到第二臺上。

LeastActive

  • 最少活躍調用數,相同活躍數的隨機,活躍數指調用先後計數差。
  • 使慢的提供者收到更少請求,由於越慢的提供者的調用先後計數差會越大。

ConsistentHash

  • 一致性 Hash,相同參數的請求老是發到同一提供者。
  • 當某一臺提供者掛時,本來發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引發劇烈變更。
  • 缺省只對第一個參數 Hash,若是要修改,請配置 <dubbo:parameter key="hash.arguments" value="0,1" />
  • 缺省用 160 份虛擬節點,若是要修改,請配置 <dubbo:parameter key="hash.nodes" value="320" />

 

3.3. Dubbo 集羣容錯策略 ?

 

 

  • Failover - 失敗自動切換,當出現失敗,重試其它服務器。一般用於讀操做,但重試會帶來更長延遲。可經過 retries="2" 來設置重試次數(不含第一次)。
  • Failfast - 快速失敗,只發起一次調用,失敗當即報錯。一般用於非冪等性的寫操做,好比新增記錄。
  • Failsafe - 失敗安全,出現異常時,直接忽略。一般用於寫入審計日誌等操做。
  • Failback - 失敗自動恢復,後臺記錄失敗請求,定時重發。一般用於消息通知操做。
  • Forking - 並行調用多個服務器,只要一個成功即返回。一般用於實時性要求較高的讀操做,但須要浪費更多服務資源。可經過 forks="2" 來設置最大並行數。
  • Broadcast - 播調用全部提供者,逐個調用,任意一臺報錯則報錯。一般用於通知全部提供者更新緩存或日誌等本地資源信息。

 

3.4. 動態代理策略?

Dubbo 做爲 RPC 框架,首先要完成的就是跨系統,跨網絡的服務調用。消費方與提供方遵循統一的接口定義,消費方調用接口時,Dubbo 將其轉換成統一格式的數據結構,經過網絡傳輸,提供方根據規則找到接口實現,經過反射完成調用。也就是說,消費方獲取的是對遠程服務的一個代理(Proxy),而提供方由於要支持不一樣的接口實現,須要一個包裝層(Wrapper)。調用的過程大概是這樣:

 

 

 

消費方的 Proxy 和提供方的 Wrapper 得以讓 Dubbo 構建出複雜、統一的體系。而這種動態代理與包裝也是經過基於 SPI 的插件方式實現的,它的接口就是ProxyFactory

@SPI("javassist")
public interface ProxyFactory {

    @Adaptive({Constants.PROXY_KEY})
    <T> T getProxy(Invoker<T> invoker) throws RpcException;

    @Adaptive({Constants.PROXY_KEY})
    <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;

}

ProxyFactory 有兩種實現方式,一種是基於 JDK 的代理實現,一種是基於 javassist 的實現。ProxyFactory 接口上定義了@SPI("javassist"),默認爲 javassist 的實現。

 

3.5. Dubbo 支持哪些序列化協議?Hessian?Hessian 的數據結構?

  1. dubbo 序列化,阿里尚不成熟的 java 序列化實現。
  2. hessian2 序列化:hessian 是一種跨語言的高效二進制的序列化方式,但這裏實際不是原生的 hessian2 序列化,而是阿里修改過的 hessian lite,它是 dubbo RPC 默認啓用的序列化方式。
  3. json 序列化:目前有兩種實現,一種是採用的阿里的 fastjson 庫,另外一種是採用 dubbo 中自已實現的簡單 json 庫,通常狀況下,json 這種文本序列化性能不如二進制序列化。
  4. java 序列化:主要是採用 JDK 自帶的 java 序列化實現,性能很不理想。
  5. Kryo 和 FST:Kryo 和 FST 的性能依然廣泛優於 hessian 和 dubbo 序列化。

Hessian 序列化與 Java 默認的序列化區別?

Hessian 是一個輕量級的 remoting on http 工具,採用的是 Binary RPC 協議,因此它很適合於發送二進制數據,同時又具備防火牆穿透能力。

  1. Hessian 支持跨語言串行
  2. 比 java 序列化具備更好的性能和易用性
  3. 支持的語言比較多

 

3.6. Protoco Buffer 是什麼?

Protocol Buffer 是 Google 出品的一種輕量 & 高效的結構化數據存儲格式,性能比 Json、XML 真的強!太!多!

Protocol Buffer 的序列化 & 反序列化簡單 & 速度快的緣由是:

  1. 編碼 / 解碼 方式簡單(只須要簡單的數學運算 = 位移等等)
  2. 採用 Protocol Buffer 自身的框架代碼 和 編譯器 共同完成

Protocol Buffer 的數據壓縮效果好(即序列化後的數據量體積小)的緣由是:

  1. 採用了獨特的編碼方式,如 Varint、Zigzag 編碼方式等等
  2. 採用 T - L - V 的數據存儲方式:減小了分隔符的使用 & 數據存儲得緊湊

 

3.7. 註冊中心掛了能夠繼續通訊嗎?

能夠。Dubbo 消費者在應用啓動時會從註冊中心拉取已註冊的生產者的地址接口,並緩存在本地。每次調用時,按照本地存儲的地址進行調用。

 

3.8. ZooKeeper 原理是什麼?ZooKeeper 有什麼用?

ZooKeeper 是一個分佈式應用協調系統,已經用到了許多分佈式項目中,用來完成統一命名服務、狀態同步服務、集羣管理、分佈式應用配置項的管理等工做。

  1. 每一個 Server 在內存中存儲了一份數據;
  2. Zookeeper 啓動時,將從實例中選舉一個 leader(Paxos 協議);
  3. Leader 負責處理數據更新等操做(Zab 協議);
  4. 一個更新操做成功,當且僅當大多數 Server 在內存中成功修改數據。

 

3.9. Netty 有什麼用?NIO/BIO/AIO 有什麼用?有什麼區別?

Netty 是一個「網絡通信框架」。

Netty 進行事件處理的流程。Channel是鏈接的通道,是 ChannelEvent 的產生者,而ChannelPipeline能夠理解爲 ChannelHandler 的集合。

 

 

IO 的方式一般分爲幾種:

  • 同步阻塞的 BIO
  • 同步非阻塞的 NIO
  • 異步非阻塞的 AIO

在使用同步 I/O 的網絡應用中,若是要同時處理多個客戶端請求,或是在客戶端要同時和多個服務器進行通信,就必須使用多線程來處理。

NIO 基於 Reactor,當 socket 有流可讀或可寫入 socket 時,操做系統會相應的通知引用程序進行處理,應用再將流讀取到緩衝區或寫入操做系統。也就是說,這個時候,已經不是一個鏈接就要對應一個處理線程了,而是有效的請求,對應一個線程,當鏈接沒有數據時,是沒有工做線程來處理的。

與 NIO 不一樣,當進行讀寫操做時,只須直接調用 API 的 read 或 write 方法便可。這兩種方法均爲異步的,對於讀操做而言,當有流可讀取時,操做系統會將可讀的流傳入 read 方法的緩衝區,並通知應用程序;對於寫操做而言,當操做系統將 write 方法傳遞的流寫入完畢時,操做系統主動通知應用程序。 便可以理解爲,read/write 方法都是異步的,完成後會主動調用回調函數。

 

3.10. 爲何要進行系統拆分?拆分不用 Dubbo 能夠嗎?

系統拆分從資源角度分爲:應用拆分和數據庫拆分。

從採用的前後順序可分爲:水平擴展、垂直拆分、業務拆分、水平拆分。

 

 

是否使用服務依據實際業務場景來決定。

當垂直應用愈來愈多,應用之間交互不可避免,將核心業務抽取出來,做爲獨立的服務,逐漸造成穩定的服務中心,使前端應用能更快速的響應多變的市場需求。此時,用於提升業務複用及整合的分佈式服務框架(RPC)是關鍵。

當服務愈來愈多,容量的評估,小服務資源的浪費等問題逐漸顯現,此時需增長一個調度中心基於訪問壓力實時管理集羣容量,提升集羣利用率。此時,用於提升機器利用率的資源調度和治理中心(SOA)是關鍵。

 

3.11. Dubbo 和 Thrift 有什麼區別?

  • Thrift 是跨語言的 RPC 框架。
  • Dubbo 支持服務治理,而 Thrift 不支持。

免費Java資料須要本身領取,涵蓋了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo高併發分佈式等教程,一共30G。 
傳送門: https://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q

相關文章
相關標籤/搜索