1、緩存在系統中用來作什麼node
1. 少許數據存儲,高速讀寫訪問。經過數據所有in-momery 的方式來保證高速訪問,同時提供數據落地的功能,實際這正是Redis最主要的適用場景。redis
2. 海量數據存儲,分佈式系統支持,數據一致性保證,方便的集羣節點添加/刪除。Redis3.0之後開始支持集羣,實現了半自動化的數據分片,不過須要smart-client的支持。數據庫
2、從不一樣的角度來詳細介紹redis編程
網絡模型:Redis使用單線程的IO複用模型,本身封裝了一個簡單的AeEvent事件處理框架,主要實現了epoll、kqueue和select,對於單純只有IO操做來講,單線程能夠將速度優點發揮到最大,可是Redis也提供了一些簡單的計算功能,好比排序、聚合等,對於這些操做,單線程模型實際會嚴重影響總體吞吐量,CPU計算過程當中,整個IO調度都是被阻塞住的。緩存
內存管理:Redis使用現場申請內存的方式來存儲數據,而且不多使用free-list等方式來優化內存分配,會在必定程度上存在內存碎片,Redis跟據存儲命令參數,會把帶過時時間的數據單獨存放在一塊兒,並把它們稱爲臨時數據,非臨時數據是永遠不會被剔除的,即使物理內存不夠,致使swap也不會剔除任何非臨時數據(但會嘗試剔除部分臨時數據),這點上Redis更適合做爲存儲而不是cache。服務器
數據一致性問題:在一致性問題上,我的感受redis沒有memcached實現的好,Memcached提供了cas命令,能夠保證多個併發訪問操做同一份數據的一致性問題。 Redis沒有提供cas 命令,並不能保證這點,不過Redis提供了事務的功能,能夠保證一串命令的原子性,中間不會被任何操做打斷。網絡
支持的KEY類型:Redis除key/value以外,還支持list,set,sorted set,hash等衆多數據結構,提供了KEYS進行枚舉操做,但不能在線上使用,若是須要枚舉線上數據,Redis提供了工具能夠直接掃描其dump文件,枚舉出全部數據,Redis還同時提供了持久化和複製等功能。數據結構
客戶端支持:redis官方提供了豐富的客戶端支持,包括了絕大多數編程語言的客戶端,好比我這次測試就選擇了官方推薦了Java客戶端Jedis.裏面提供了豐富的接口、方法使得開發人員無需關係內部的數據分片、讀取數據的路由等,只需簡單的調用便可,很是方便。併發
數據複製:從2.8開始,Slave會週期性(每秒一次)發起一個Ack確認複製流(replication stream)被處理進度, Redis複製工做原理詳細過程以下:app
1. 若是設置了一個Slave,不管是第一次鏈接仍是重連到Master,它都會發出一個SYNC命令;
2. 當Master收到SYNC命令以後,會作兩件事:
a) Master執行BGSAVE:後臺寫數據到磁盤(rdb快照);
b) Master同時將新收到的寫入和修改數據集的命令存入緩衝區(非查詢類);
3. 當Master在後臺把數據保存到快照文件完成以後,Master會把這個快照文件傳送給Slave,而Slave則把內存清空後,加載該文件到內存中;
4. 而Master也會把此前收集到緩衝區中的命令,經過Reids命令協議形式轉發給Slave,Slave執行這些命令,實現和Master的同步;
5. Master/Slave此後會不斷經過異步方式進行命令的同步,達到最終數據的同步一致;
6. 須要注意的是Master和Slave之間一旦發生重連都會引起全量同步操做。但在2.8以後,也多是部分同步操做。
2.8開始,當Master和Slave之間的鏈接斷開以後,他們之間能夠採用持續複製處理方式代替採用全量同步。
Master端爲複製流維護一個內存緩衝區(in-memory backlog),記錄最近發送的複製流命令;同時,Master和Slave之間都維護一個複製偏移量(replication offset)和當前Master服務器ID(Masterrun id)。
當網絡斷開,Slave嘗試重連時:
a. 若是MasterID相同(即還是斷網前的Master服務器),而且從斷開時到當前時刻的歷史命令依然在Master的內存緩衝區中存在,則Master會將缺失的這段時間的全部命令發送給Slave執行,而後複製工做就能夠繼續執行了;
b. 不然,依然須要全量複製操做。
讀寫分離:redis支持讀寫分離,並且使用簡單,只需在配置文件中把redis讀服務器和寫服務器進行配置,多個服務器使用逗號分開以下:
水平動態擴展:歷時三年之久,終於等來了期待已由的Redis 3.0。新版本主要是實現了Cluster的功能,增刪集羣節點後會自動的進行數據遷移。實現 Redis 集羣在線重配置的核心就是將槽從一個節點移動到另外一個節點的能力。由於一個哈希槽實際上就是一些鍵的集合, 因此 Redis 集羣在重哈希(rehash)時真正要作的,就是將一些鍵從一個節點移動到另外一個節點。
數據淘汰策略:redis 內存數據集大小上升到必定大小的時候,就會施行數據淘汰策略。redis 提供 6種數據淘汰策略:
volatile-lru:從已設置過時時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰
volatile-ttl:從已設置過時時間的數據集(server.db[i].expires)中挑選將要過時的數據淘汰
volatile-random:從已設置過時時間的數據集(server.db[i].expires)中任意選擇數據淘汰
allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
no-enviction(驅逐):禁止驅逐數據
3、集羣(即分佈式)
下面詳細介紹一下redis的集羣功能,從3.0之後的版本開始支持集羣功能,也就是正真意義上實現了分佈式。
Redis 集羣是一個分佈式(distributed)、容錯(fault-tolerant)的 Redis 實現, 集羣可使用的功能是普通單機 Redis 所能使用的功能的一個子集(subset)。
Redis 集羣中不存在中心(central)節點或者代理(proxy)節點, 集羣的其中一個主要設計目標是達到線性可擴展性(linear scalability)。
Redis 集羣爲了保證一致性(consistency)而犧牲了一部分容錯性: 系統會在保證對網絡斷線(netsplit)和節點失效(node failure)具備有限(limited)抵抗力的前提下,儘量地保持數據的一致性。
集羣特性:
(1)全部的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬。
(2)節點的fail是經過集羣中超過半數的節點檢測失效時才生效。
(3)客戶端與redis節點直連,不須要中間proxy層.客戶端不須要鏈接集羣全部節點,鏈接集羣中任何一個可用節點便可。
(4)redis-cluster把全部的物理節點映射到[0-16383]slot上,cluster 負責維護node<->slot<->value
Redis 集羣實現的功能子集:
Redis集羣實現了單機 Redis 中, 全部處理單個數據庫鍵的命令。針對多個數據庫鍵的複雜計算操做, 好比集合的並集操做、合集操做沒有被實現,那些理論上須要使用多個節點的多個數據庫鍵才能完成的命令也沒有被實現。在未來, 用戶也許能夠經過 MIGRATE COPY 命令,在集羣的計算節點(computation node)中執行鍼對多個數據庫鍵的只讀操做, 但集羣自己不會去實現那些須要將多個數據庫鍵在多個節點中移來移去的複雜多鍵命令。
Redis 集羣不像單機Redis 那樣支持多數據庫功能, 集羣只使用默認的 0 號數據庫, 而且不能使用 SELECT 命令。
Redis 集羣協議中的客戶端和服務器:
Redis 集羣中的節點有如下責任:
1. 持有鍵值對數據。
2. 記錄集羣的狀態,包括鍵到正確節點的映射(mappingkeys to right nodes)。
3. 自動發現其餘節點,識別工做不正常的節點,並在有須要時,在從節點中選舉出新的主節點。
爲了執行以上列出的任務, 集羣中的每一個節點都與其餘節點創建起了「集羣鏈接(cluster bus)」, 該鏈接是一個 TCP 鏈接, 使用二進制協議進行通信。
節點之間使用Gossip 協議 來進行如下工做:
1. 傳播(propagate)關於集羣的信息,以此來發現新的節點。
2. 向其餘節點發送 PING 數據包,以此來檢查目標節點是否正常運做。
3. 在特定事件發生時,發送集羣信息。
4. 除此以外, 集羣鏈接還用於在集羣中發佈或訂閱信息。
由於集羣節點不能代理(proxy)命令請求, 因此客戶端應該在節點返回 -MOVED 或者 -ASK 轉向(redirection)錯誤時,自行將命令請求轉發至其餘節點。由於客戶端能夠自由地向集羣中的任何一個節點發送命令請求, 並能夠在有須要時, 根據轉向錯誤所提供的信息, 將命令轉發至正確的節點,因此在理論上來講, 客戶端是無須保存集羣狀態信息的。不過, 若是客戶端能夠將鍵和節點之間的映射信息保存起來, 能夠有效地減小可能出現的轉向次數, 籍此提高命令執行的效率。
鍵分佈模型
Redis 集羣的鍵空間被分割爲 16384 個槽(slot), 集羣的最大節點數量也是 16384 個。
推薦的最大節點數量爲 1000 個左右。每一個主節點都負責處理 16384 個哈希槽的其中一部分。
當咱們說一個集羣處於「穩定」(stable)狀態時, 指的是集羣沒有在執行重配(reconfiguration)操做,每一個哈希槽都只由一個節點進行處理。重配置指的是將某個/某些槽從一個節點移動到另外一個節點。一個主節點能夠有任意多個從節點,這些從節點用於在主節點發生網絡斷線或者節點失效時, 對主節點進行替換。
集羣節點屬性:
每一個節點在集羣中都有一個獨一無二的 ID , 該 ID 是一個十六進制表示的 160 位隨機數, 在節點第一次啓動時由 /dev/urandom 生成。
節點會將它的 ID 保存到配置文件, 只要這個配置文件不被刪除,節點就會一直沿用這個 ID 。節點 ID 用於標識集羣中的每一個節點。一個節點能夠改變它的 IP 和端口號, 而不改變節點 ID 。集羣能夠自動識別出 IP/端口號的變化, 並將這一信息經過 Gossip 協議廣播給其餘節點知道。
如下是每一個節點都有的關聯信息, 而且節點會將這些信息發送給其餘節點:
1. 節點所使用的 IP 地址和 TCP 端口號。
2. 節點的標誌(flags)。
3. 節點負責處理的哈希槽。
4. 節點最近一次使用集羣鏈接發送 PING 數據包(packet)的時間。
5. 節點最近一次在回覆中接收到 PONG 數據包的時間。
6. 集羣將該節點標記爲下線的時間。
7. 該節點的從節點數量。
8. 若是該節點是從節點的話,那麼它會記錄主節點的節點 ID 。若是這是一個主節點的話,那麼主節點 ID 這一欄的值爲 0000000 。
以上信息的其中一部分能夠經過向集羣中的任意節點(主節點或者從節點均可以)發送 CLUSTER NODES 命令來得到。
節點握手:
節點老是應答(accept)來自集羣鏈接端口的鏈接請求,並對接收到的 PING 數據包進行回覆, 即便這個 PING 數據包來自不可信的節點。然而,除了 PING 以外, 節點會拒絕其餘全部並不是來自集羣節點的數據包。要讓一個節點認可另外一個節點同屬於一個集羣,只有如下兩種方法:
1. 一個節點能夠經過向另外一個節點發送 MEET 信息,來強制讓接收信息的節點認可發送信息的節點爲集羣中的一份子。 一個節點僅在管理員顯式地向它發送CLUSTER MEET ipport 命令時, 纔會向另外一個節點發送 MEET 信息。
2. 若是一個可信節點向另外一個節點傳播第三者節點的信息, 那麼接收信息的那個節點也會將第三者節點識別爲集羣中的一份子。也便是說, 若是 A 認識 B , B 認識 C , 而且 B 向 A 傳播關於 C 的信息, 那麼 A 也會將 C 識別爲集羣中的一份子, 並嘗試鏈接 C 。
這意味着若是咱們將一個/一些新節點添加到一個集羣中, 那麼這個/這些新節點最終會和集羣中已有的其餘全部節點鏈接起來。
這說明只要管理員使用 CLUSTER MEET 命令顯式地指定了可信關係,集羣就能夠自動發現其餘節點。這種節點識別機制經過防止不一樣的 Redis 集羣由於 IP 地址變動或者其餘網絡事件的發生而產生意料以外的聯合(mix), 從而使得集羣更具健壯性。當節點的網絡鏈接斷開時,它會主動鏈接其餘已知的節點。
MOVED 轉向:
一個 Redis 客戶端能夠向集羣中的任意節點(包括從節點)發送命令請求。節點會對命令請求進行分析, 若是該命令是集羣能夠執行的命令, 那麼節點會查找這個命令所要處理的鍵所在的槽。若是要查找的哈希槽正好就由接收到命令的節點負責處理,那麼節點就直接執行這個命令。另外一方面, 若是所查找的槽不是由該節點處理的話, 節點將查看自身內部所保存的哈希槽到節點 ID 的映射記錄,並向客戶端回覆一個 MOVED 錯誤。
即便客戶端在從新發送 GET 命令以前, 等待了很是久的時間,以致於集羣又再次更改了配置, 使得節點 127.0.0.1:6381 已經再也不處理槽 3999 , 那麼當客戶端向節點 127.0.0.1:6381 發送 GET 命令的時候, 節點將再次向客戶端返回 MOVED 錯誤, 指示如今負責處理槽 3999 的節點。
雖然咱們用 ID 來標識集羣中的節點, 可是爲了讓客戶端的轉向操做盡量地簡單,,節點在 MOVED 錯誤中直接返回目標節點的 IP 和端口號,而不是目標節點的 ID 。但一個客戶端應該記錄(memorize)下「槽 3999 由節點 127.0.0.1:6381 負責處理「這一信息, 這樣當再次有命令須要對槽 3999 執行時, 客戶端就能夠加快尋找正確節點的速度。
注意, 當集羣處於穩定狀態時, 全部客戶端最終都會保存有一個哈希槽至節點的映射記錄(map of hash slots to nodes), 使得集羣很是高效: 客戶端能夠直接向正確的節點發送命令請求, 無須轉向、代理或者其餘任何可能發生單點故障(single point failure)的實體(entiy)。
除了 MOVED轉向錯誤以外, 一個客戶端還應該能夠處理稍後介紹的 ASK 轉向錯誤。
集羣在線重配置:
Redis 集羣支持在集羣運行的過程當中添加或者移除節點。實際上, 節點的添加操做和節點的刪除操做能夠抽象成同一個操做,那就是, 將哈希槽從一個節點移動到另外一個節點:添加一個新節點到集羣, 等於將其餘已存在節點的槽移動到一個空白的新節點裏面。從集羣中移除一個節點, 等於將被移除節點的全部槽移動到集羣的其餘節點上面去。
所以, 實現Redis 集羣在線重配置的核心就是將槽從一個節點移動到另外一個節點的能力。 由於一個哈希槽實際上就是一些鍵的集合, 因此 Redis 集羣在重哈希(rehash)時真正要作的, 就是將一些鍵從一個節點移動到另外一個節點。
要理解Redis 集羣如何將槽從一個節點移動到另外一個節點, 咱們須要對 CLUSTER 命令的各個子命令進行介紹,這些命理負責管理集羣節點的槽轉換表(slots translation table)。
如下是CLUSTER 命令可用的子命令:
最開頭的兩條命令ADDSLOTS 和 DELSLOTS 分別用於向節點指派(assign)或者移除節點,當槽被指派或者移除以後, 節點會將這一信息經過 Gossip 協議傳播到整個集羣。 ADDSLOTS 命令一般在新建立集羣時, 做爲一種快速地將各個槽指派給各個節點的手段來使用。
CLUSTERSETSLOT slot NODE node 子命令能夠將指定的槽 slot 指派給節點node 。
至於CLUSTER SETSLOT slot MIGRATING node 命令和 CLUSTER SETSLOTslot IMPORTING node 命令, 前者用於將給定節點 node 中的槽 slot 遷移出節點, 然後者用於將給定槽 slot導入到節點 node :
當一個槽被設置爲MIGRATING 狀態時, 原來持有這個槽的節點仍然會繼續接受關於這個槽的命令請求, 但只有命令所處理的鍵仍然存在於節點時, 節點纔會處理這個命令請求。
若是命令所使用的鍵不存在與該節點, 那麼節點將向客戶端返回一個 -ASK 轉向(redirection)錯誤, 告知客戶端, 要將命令請求發送到槽的遷移目標節點。
當一個槽被設置爲IMPORTING 狀態時, 節點僅在接收到 ASKING 命令以後, 纔會接受關於這個槽的命令請求。
若是客戶端沒有向節點發送 ASKING 命令, 那麼節點會使用 -MOVED 轉向錯誤將命令請求轉向至真正負責處理這個槽的節點。
上面關於MIGRATING 和 IMPORTING 的說明有些難懂, 讓咱們用一個實際的實例來講明一下。
假設如今, 咱們有 A 和 B 兩個節點, 而且咱們想將槽8 從節點 A 移動到節點 B , 因而咱們:
向節點 B 發送命令 CLUSTER SETSLOT 8 IMPORTING A
向節點 A 發送命令 CLUSTER SETSLOT 8 MIGRATING B
每當客戶端向其餘節點發送關於哈希槽 8 的命令請求時, 這些節點都會向客戶端返回指向節點 A 的轉向信息:
若是命令要處理的鍵已經存在於槽 8 裏面, 那麼這個命令將由節點 A 處理。
若是命令要處理的鍵未存在於槽 8 裏面(好比說,要向槽添加一個新的鍵), 那麼這個命令由節點 B 處理。
這種機制將使得節點 A 再也不建立關於槽 8 的任何新鍵。
與此同時, 一個特殊的客戶端 redis-trib 以及 Redis 集羣配置程序(configuration utility)會將節點 A 中槽 8 裏面的鍵移動到節點 B 。
鍵的移動操做由如下兩個命令執行:
CLUSTERGETKEYSINSLOT slot count
上面的命令會讓節點返回 count 個 slot 槽中的鍵, 對於命令所返回的每一個鍵, redis-trib 都會向節點 A 發送一條 MIGRATE 命令, 該命令會將所指定的鍵原子地(atomic)從節點 A 移動到節點 B (在移動鍵期間,兩個節點都會處於阻塞狀態,以避免出現競爭條件)。
如下爲MIGRATE 命令的運做原理:
MIGRATEtarget_host target_port key target_database id timeout
執行MIGRATE 命令的節點會鏈接到 target 節點, 並將序列化後的 key 數據發送給 target , 一旦 target 返回 OK , 節點就將本身的 key 從數據庫中刪除。
從一個外部客戶端的視角來看, 在某個時間點上, 鍵 key 要麼存在於節點 A , 要麼存在於節點 B , 但不會同時存在於節點 A 和節點 B 。
由於 Redis集羣只使用 0 號數據庫, 因此當 MIGRATE 命令被用於執行集羣操做時, target_database 的值老是 0 。
target_database參數的存在是爲了讓 MIGRATE 命令成爲一個通用命令, 從而能夠做用於集羣之外的其餘功能。
咱們對MIGRATE 命令作了優化, 使得它即便在傳輸包含多個元素的列表鍵這樣的複雜數據時, 也能夠保持高效。
不過, 儘管MIGRATE 很是高效, 對一個鍵很是多、而且鍵的數據量很是大的集羣來講, 集羣重配置仍是會佔用大量的時間, 可能會致使集羣沒辦法適應那些對於響應時間有嚴格要求的應用程序。
ASK 轉向:
在以前介紹 MOVED 轉向的時候, 咱們說除了 MOVED 轉向以外, 還有另外一種 ASK 轉向。當節點須要讓一個客戶端長期地(permanently)將針對某個槽的命令請求發送至另外一個節點時,節點向客戶端返回 MOVED 轉向。另外一方面, 當節點須要讓客戶端僅僅在下一個命令請求中轉向至另外一個節點時, 節點向客戶端返回 ASK 轉向。
好比說, 在咱們上一節列舉的槽 8 的例子中, 由於槽 8 所包含的各個鍵分散在節點 A 和節點 B 中, 因此當客戶端在節點 A 中沒找到某個鍵時, 它應該轉向到節點 B 中去尋找, 可是這種轉向應該僅僅影響一次命令查詢,而不是讓客戶端每次都直接去查找節點 B : 在節點 A 所持有的屬於槽 8 的鍵沒有所有被遷移到節點 B 以前, 客戶端應該先訪問節點 A , 而後再訪問節點 B 。由於這種轉向只針對 16384 個槽中的其中一個槽, 因此轉向對集羣形成的性能損耗屬於可接受的範圍。
由於上述緣由, 若是咱們要在查找節點 A 以後, 繼續查找節點 B , 那麼客戶端在向節點 B 發送命令請求以前, 應該先發送一個 ASKING 命令, 不然這個針對帶有IMPORTING 狀態的槽的命令請求將被節點 B 拒絕執行。接收到客戶端 ASKING 命令的節點將爲客戶端設置一個一次性的標誌(flag), 使得客戶端能夠執行一次針對 IMPORTING 狀態的槽的命令請求。從客戶端的角度來看, ASK 轉向的完整語義(semantics)以下:
1. 若是客戶端接收到 ASK 轉向, 那麼將命令請求的發送對象調整爲轉向所指定的節點。
2. 先發送一個 ASKING 命令,而後再發送真正的命令請求。
3. 沒必要更新客戶端所記錄的槽 8 至節點的映射: 槽 8 應該仍然映射到節點 A , 而不是節點 B 。
一旦節點 A 針對槽 8 的遷移工做完成, 節點 A 在再次收到針對槽 8 的命令請求時, 就會向客戶端返回 MOVED 轉向, 將關於槽 8 的命令請求長期地轉向到節點 B 。
注意, 即便客戶端出現 Bug , 過早地將槽 8 映射到了節點 B 上面, 但只要這個客戶端不發送 ASKING 命令, 客戶端發送命令請求的時候就會趕上 MOVED 錯誤, 並將它轉向回節點 A 。
容錯:
節點失效檢測,如下是節點失效檢查的實現方法:
1. 當一個節點向另外一個節點發送 PING 命令, 可是目標節點未能在給定的時限內返回 PING 命令的回覆時, 那麼發送命令的節點會將目標節點標記爲 PFAIL(possible failure,可能已失效)。等待 PING 命令回覆的時限稱爲「節點超時時限(node timeout)」, 是一個節點選項(node-wise setting)。
2. 每次當節點對其餘節點發送 PING 命令的時候,它都會隨機地廣播三個它所知道的節點的信息, 這些信息裏面的其中一項就是說明節點是否已經被標記爲 PFAIL或者 FAIL 。
當節點接收到其餘節點發來的信息時, 它會記下那些被其餘節點標記爲失效的節點。這稱爲失效報告(failure report)。
3. 若是節點已經將某個節點標記爲 PFAIL , 而且根據節點所收到的失效報告顯式,集羣中的大部分其餘主節點也認爲那個節點進入了失效狀態, 那麼節點會將那個失效節點的狀態標記爲 FAIL 。
4. 一旦某個節點被標記爲 FAIL , 關於這個節點已失效的信息就會被廣播到整個集羣,全部接收到這條信息的節點都會將失效節點標記爲 FAIL 。
簡單來講, 一個節點要將另外一個節點標記爲失效, 必須先詢問其餘節點的意見, 而且獲得大部分主節點的贊成才行。由於過時的失效報告會被移除,因此主節點要將某個節點標記爲 FAIL 的話, 必須以最近接收到的失效報告做爲根據。
從節點選舉:一旦某個主節點進入 FAIL 狀態, 若是這個主節點有一個或多個從節點存在,那麼其中一個從節點會被升級爲新的主節點, 而其餘從節點則會開始對這個新的主節點進行復制。
新的主節點由已下線主節點屬下的全部從節點中自行選舉產生,如下是選舉的條件:
1. 這個節點是已下線主節點的從節點。
2. 已下線主節點負責處理的槽數量非空。
3. 從節點的數據被認爲是可靠的, 也便是, 主從節點之間的複製鏈接(replication link)的斷線時長不能超過節點超時時限(nodetimeout)乘以REDIS_CLUSTER_SLAVE_VALIDITY_MULT 常量得出的積。
若是一個從節點知足了以上的全部條件, 那麼這個從節點將向集羣中的其餘主節點發送受權請求, 詢問它們,是否容許本身(從節點)升級爲新的主節點。
若是發送受權請求的從節點知足如下屬性, 那麼主節點將向從節點返FAILOVER_AUTH_GRANTED 受權, 贊成從節點的升級要求:
1. 發送受權請求的是一個從節點, 而且它所屬的主節點處於 FAIL狀態。
2. 在已下線主節點的全部從節點中, 這個從節點的節點 ID 在排序中是最小的。
3. 這個從節點處於正常的運行狀態: 它沒有被標記爲 FAIL 狀態,也沒有被標記爲 PFAIL 狀態。
一旦某個從節點在給定的時限內獲得大部分主節點的受權,它就會開始執行如下故障轉移操做:
1. 經過 PONG 數據包(packet)告知其餘節點, 這個節點如今是主節點了。
2. 經過 PONG 數據包告知其餘節點, 這個節點是一個已升級的從節點(promoted slave)。
3. 接管(claiming)全部由已下線主節點負責處理的哈希槽。
4. 顯式地向全部節點廣播一個 PONG 數據包, 加速其餘節點識別這個節點的進度,而不是等待定時的 PING / PONG 數據包。
全部其餘節點都會根據新的主節點對配置進行相應的更新:
全部被新的主節點接管的槽會被更新。
已下線主節點的全部從節點會察覺到 PROMOTED 標誌,並開始對新的主節點進行復制。
若是已下線的主節點從新回到上線狀態, 那麼它會察覺到PROMOTED 標誌, 並將自身調整爲現任主節點的從節點。
在集羣的生命週期中, 若是一個帶有 PROMOTED 標識的主節點由於某些緣由轉變成了從節點,那麼該節點將丟失它所帶有的 PROMOTED 標識。