redis的集群方式主要有以下三種:
1、 主從模式
master掛掉之后,slave仍能正常讀,但redis不再提供寫服務,直到master重新啟動
slave掛掉之后不影響其他slave的讀和master的讀寫,slave重啟后重新同步master數(shù)據(jù)
主寫從讀:
主庫寫,從庫讀,從庫掛掉之后從主庫讀。
主讀寫從備份:
主庫讀寫,從庫只做備份。主庫掛掉之后,redis不再工作
主從一致:
從庫啟動后,主動向master發(fā)送SYNC命令,master將保存快照(RDB持久化數(shù)據(jù))和 保存快照到當前時間的緩存命令 發(fā)送給slave。slave接收消息后加載快照和執(zhí)行緩存命令
slave上線后,master每次接收寫命令都會發(fā)給slave,保證主從一致。
缺點:
master掛掉之后不能再提供寫服務。單點故障
優(yōu)點:
簡單,易維護。省資源
2、哨兵模式
監(jiān)控redis集群的狀態(tài),在master掛掉之后,重新選擇新的master。選擇機制:
- 使用如下條件篩選備選node:
- slave節(jié)點狀態(tài)處于S_DOWN,O_DOWN,DISCONNECTED的除外
- 最近一次ping應答時間不超過5倍ping的間隔(假如ping的間隔為1秒,則最近一次應答延遲不應超過5秒,redis sentinel默認為1秒)
- info_refresh應答不超過3倍info_refresh的間隔(原理同2,redis sentinel默認為10秒)
- slave節(jié)點與master節(jié)點失去聯(lián)系的時間不能超過( (now - master->s_down_since_time) + (master->down_after_period * 10))??傮w意思是說,slave節(jié)點與master同步太不及時的(比如新啟動的節(jié)點),不應該參與被選舉。
- Slave priority不等于0(這個是在配置文件中指定,默認配置為100)。
- 從備選node中,按照如下順序選擇新的master
- 較低的slave_priority(這個是在配置文件中指定,默認配置為100)
- 較大的replication offset(每個slave在與master同步后offset自動增加)
- 較小的runid(每個redis實例,都會有一個runid,通常是一個40位的隨機字符串,在redis啟動時設置,重復概率非常小)
- 如果以上條件都不足以區(qū)別出唯一的節(jié)點,則會看哪個slave節(jié)點處理之前master發(fā)送的command多,就選誰。
哨兵也是有集群的,哨兵之前也是互相監(jiān)控的,哨兵和redis集群之前是多對多的關系。
哨兵監(jiān)控master流程:
- 哨兵每秒向master、slave發(fā)送一次ping命令,每10s發(fā)送一次info命令。
- 如果實例回復的時間比設置的時間要晚,則實例會被標記為主觀下線
- 如果master被標記為主觀下線,則監(jiān)控該master的所有哨兵會向該master每秒發(fā)送一次ping,確認其下線。
- 當有足夠多的哨兵確認了該master的下線狀態(tài),則該master就會被標記為客觀下線。
- 如果master被標記為客觀下線,則哨兵向所有slave發(fā)送INFO命令每s一次。
- 若沒有足夠多的哨兵同意master下線則master客觀下線狀態(tài)會被解除。若master重新向哨兵相應,則master主觀下線狀態(tài)解除。
3、集群模式
可以說是哨兵模式和主從模式的結合。cluster模式有多個節(jié)點,每個節(jié)點都有主從。主要解決單機redis內(nèi)存不夠的問題。
redis集群通過哈希槽將redis數(shù)據(jù)分布式存儲到集群的master節(jié)點中,slave節(jié)點不工作,僅在master節(jié)點掛掉之后替換master繼續(xù)提供服務。
redis每個節(jié)點負責一部分哈希槽位。
集群節(jié)點的擴展/收縮方式:
- 首先啟動一個 Redis 節(jié)點,記為 M4。
- 使用 cluster meet 命令,讓新 Redis 節(jié)點加入到集群中。新節(jié)點剛開始都是主節(jié)點狀態(tài),由于沒有負責的>槽,所以不能接受任何讀寫操作,后續(xù)我們就給他遷移槽和填充數(shù)據(jù)。
- 對 M4 節(jié)點發(fā)送 cluster setslot { slot } importing { sourceNodeId } 命令,讓目標節(jié)點準備導入槽的數(shù)據(jù)。 >4) 對源節(jié)點,也就是 M1,M2,M3 節(jié)點發(fā)送 cluster setslot { slot } migrating { targetNodeId } 命令,讓源節(jié)>點準備遷出槽的數(shù)據(jù)。
- 源節(jié)點執(zhí)行 cluster getkeysinslot { slot } { count } 命令,獲取 count 個屬于槽 { slot } 的鍵,然后執(zhí)行步驟>六的操作進行遷移鍵值數(shù)據(jù)。
- 在源節(jié)點上執(zhí)行 migrate { targetNodeIp} " " 0 { timeout } keys { key... } 命令,把獲取的鍵通過 pipeline 機制>批量遷移到目標節(jié)點,批量遷移版本的 migrate 命令在 Redis 3.0.6 以上版本提供。
- 重復執(zhí)行步驟 5 和步驟 6 直到槽下所有的鍵值數(shù)據(jù)遷移到目標節(jié)點。
- 向集群內(nèi)所有主節(jié)點發(fā)送 cluster setslot { slot } node { targetNodeId } 命令,通知槽分配給目標節(jié)點。為了>保證槽節(jié)點映射變更及時傳播,需要遍歷發(fā)送給所有主節(jié)點更新被遷移的槽執(zhí)行新節(jié)點。
客戶端路由:
- smart集群客戶端維護了一張哈希槽對應節(jié)點的關系列表。
- 客戶端根據(jù)本地 slot 緩存發(fā)送命令到源節(jié)點,如果存在鍵對應則直接執(zhí)行并返回結果給客戶端。
- 如果節(jié)點返回 MOVED 錯誤,更新本地的 slot 到 Redis 節(jié)點的映射關系,然后重新發(fā)起請求。
- 如果數(shù)據(jù)正在遷移中,節(jié)點會回復 ASK 重定向異常。格式如下: ( error ) ASK { slot } { targetIP } : { targetPort }