redis 主从 哨兵 集群 及原理
1.主從哨兵
1.主從哨兵架構圖:
此圖為最常見的一主兩從結構,一個master主機,兩個slave主機。每臺主機上都運行著兩個進程:
?
主從哨兵集群的優(yōu)缺點:
- 優(yōu)點:實現了數據備份,讀負載均衡,自動化故障恢復,高可用。
- 缺點:沒有伸縮性,數據存儲的限制受到單機內存大小的限制,沒發(fā)通過增加主機來增加存儲空間。
所以,此主從哨兵在中小系統(tǒng)中廣受使用,因為其簡單好用的特性,在數據量不大的情況下,可以很好的提供服務,但是隨著互聯(lián)網企業(yè)的不斷發(fā)展,數據量越來越大,單機存儲已經無法滿足需求,于是redis官方至3.0版本后推出了新一代的集群方案,redis cluster分布式集群,此集群則在高可用的基礎上,解決了伸縮性的問題。
2.環(huán)境搭建:
由于哨兵的高可用和確保不是因為哨兵故障導致的master狀態(tài)誤判,所以集群的數量為單數最好,最低集群配置則為1主兩從,3哨兵。
即需要3臺服務器,每臺服務器上運行一個redis-server,一個redis-sentinel
1.master配置
# 允許任意用戶連接 bind 0.0.0.0 # 關閉保護模式 protected-mode no # 開啟守護進程 daemonize yes # 如果是作為緩存服務器,需要注釋掉三個數據持久化的選項 # save 900 1 # save 300 10 # save 60 10000 # 設置redis密碼,如果要設置密碼,則主從的密碼要統(tǒng)一一致,這樣在故障時切換master才能正常連接,如果不設密碼則都不設密碼 requirepass 123456 # 設置最大內存限制,避免內存過大造成服務器宕機 maxmemory 2gb2.salve配置
# 允許任意用戶連接 bind 0.0.0.0 # 關閉保護模式 protected-mode no # 開啟守護進程 daemonize yes # 如果是作為緩存服務器,需要注釋掉三個數據持久化的選項 # save 900 1 # save 300 10 # save 60 10000 # 設置redis密碼,如果要設置密碼,則主從的密碼要統(tǒng)一一致,這樣在故障時切換master才能正常連接,如果不設密碼則都不設密碼 requirepass 123456 # 設置最大內存限制,避免內存過大造成服務器宕機 maxmemory 2gb # 指定matser機的IP和端口 slaveof 192.168.0.1 6379 # master上redis的密碼,如果沒有設置密碼則不需要配置 masterauth 1234563.哨兵配置
修改sentinel.conf
# 設為后臺啟動 daemonize yes # 設置log文件路徑,方便出故障時進行排查 logfile "/var/log/redis/sentinel.log" # 關閉保護模式 protected-mode no # 設置監(jiān)控master主機,只需要配置上master的ip和端口 # 后面的2,表示有兩臺或以上哨兵認定master掛掉了,則認為master掛掉,進行選舉切換master sentinel monitor mymaster 192.168.0.1 6379 2 # 指定master和slave的統(tǒng)一密碼 sentinel auth-pass mymaster 1234563.實現原理
1)主從 master-slave
redis主從模式(master-slave,為保政治正確,已改名master-replica),提供了除持久化外另一種數據的熱備功能,也為讀寫分離提供了途徑;
redis主從模式通過復制功能實現,redis提供了SLAVEOF(REPLICAOF),讓一個服務器(slave)去復制另一個服務器(master);
復制功能的開啟: 通過客戶端向服務器發(fā)送指令:slaveof(replicaof) host port?,或者在slave配置文件中配置?replicaof選項;
注:?slaveof(replicaof) host port?是異步命令,當服務器收到該命令后,會先將host/port保存到服務器狀態(tài)(redisServer)的masterhost及masterport屬性里,然后回復 OK,再開始執(zhí)行真正的復制操作;
redis的復制功能的實現,包括?同步(SYNC/PSYNC)?和?命令傳播(command propagate)?兩個操作:
同步:
PSYNC
PSYNC提供了全量同步和部分同步兩種模式,全量同步跟?SYNC?命令類似
- 為實現數據的部分重同步,redis使用了一些定義
- ?復制偏移量:master和slave都會維護一個復制偏移量
- master 每發(fā)送一個字節(jié),將偏移量+1
- slave 每收到一個字節(jié),將偏移量+1
- 復制積壓緩沖區(qū)
- master維護的一個?固定長度?的FIFO隊列,默認1M;存放了一部分最近傳播的寫命令,并且為每個字節(jié)記錄了相應的復制偏移量;
- 服務器支行ID: 每個redis服務器,不論主從,都有自己的支行ID,在啟動服務時生成,由40個隨機的16進制字符串組成?
- ?復制偏移量:master和slave都會維護一個復制偏移量
- 有了以上三個定義,就可以實現部分同步功能了:
- slave 向 master 發(fā)送命令?PSYNC <runid> <offset>,其中 runid 表示上次復制的 master 的運行ID,offset 則是slave保存的復制偏移量;如果是第一次同步,則用??和?-1表示:PSYNC ? -1;
- master 收到命令后,查檢是第首次同步、收到的runid是否是自身的runid、根據偏移量檢查缺失的數據是否全部在復制積壓緩沖區(qū)中,然后會回復:
- +FULLRESYNC <runid> <offset>?表示將執(zhí)行全量同步;
- +CONTINUE?表示將執(zhí)行增量同步,slave 只需等待 master 繼續(xù)將增量數據發(fā)過來即可;注:當runid相同且缺失和數據都仍在復制積壓緩沖區(qū)時才會執(zhí)行部分同步;
- -ERR?表示 master 版本低于2.8,不能識別?PSYNC命令;
心跳檢測
在命令傳播階段,slave 會定時向 master 發(fā)送心跳信息,默認每秒一次,命令格式:?REPLCONF ACK <offset>
作用:
步驟:
注:master 和 slave 需要互為對方的客戶端,因為彼此都要向對方發(fā)送命令;
2)哨兵 Sentinel
master-slave方案解決了數據的復制問題,但是 當 master 宕機時,slave 并不會自動切換為新的 master,以繼續(xù)提供服務,于是,Sentinel System 有了用武之地;
由一個或多個 Sentinel 實例組成的 Sentinel System,可以監(jiān)視任意多個 master 及其 slave,并行使以下職責:
先進行哨兵功能的總結:
故障轉移:
Sentinel節(jié)點感知:
判斷下線(主觀下線、客觀下線):
選舉哨兵頭領 Sentinel Leader:
選出新的主服務器:
4.集群搭建
1.集群架構圖
2.集群配置
# 集群開關,默認是不開啟集群模式 # cluster-enabled yes#集群配置文件的名稱,每個節(jié)點都有一個集群相關的配置文件,持久化保存集群的信息。這個文件并不需要手動 配置,這個配置文件有Redis生成并更新,每個Redis集群節(jié)點需要一個單獨的配置文件,請確保與實例運行的系 統(tǒng)中配置文件名稱不沖突 # cluster-config-file nodes-6379.conf#節(jié)點互連超時的閥值。集群節(jié)點超時毫秒數 # cluster-node-timeout 15000#在進行故障轉移的時候,全部slave都會請求申請為master,但是有些slave可能與master斷開連接一段時間 了,導致數據過于陳舊,這樣的slave不應該被提升為master。該參數就是用來判斷slave節(jié)點與master斷線的時 間是否過長。判斷方法是: #比較slave斷開連接的時間和(node-timeout * slave-validity-factor) + repl-ping-slave-period #如果節(jié)點超時時間為三十秒, 并且slave-validity-factor為10,假設默認的repl-ping-slave-period是10 秒,即如果超過310秒slave將不會嘗試進行故障轉移 # cluster-replica-validity-factor 10# master的slave數量大于該值,slave才能遷移到其他孤立master上,如這個參數若被設為2,那么只有當一 個主節(jié)點擁有2 個可工作的從節(jié)點時,它的一個從節(jié)點會嘗試遷移 # cluster-migration-barrier 1#默認情況下,集群全部的slot有節(jié)點負責,集群狀態(tài)才為ok,才能提供服務。設置為no,可以在slot沒有全 部分配的時候提供服務。不建議打開該配置,這樣會造成分區(qū)的時候,小分區(qū)的master一直在接受寫請求,而 造成很長時間數據不一致 # cluster-require-full-coverage yes3.實現原理
通過主從與哨兵,redis即可實現高可用,然額,仍然存在一個問題,單臺服務器的內存是有限的,不夠用怎么辦?redis有緩存淘汰機制,可以解決一部分問題,但業(yè)務需求是無限的,當不能過期與淘汰的數據大到一臺主機不夠用時,怎么辦呢?SO,跟所有其它分布式系統(tǒng)一樣,還需要橫向擴展能力,幸好,自redis3.0開始,開始提供集群功能;
啟動集群:?當redis 服務器以集群模式啟動時,即成為一個?節(jié)點?,默認運行在一個只包含自己的集群中,使用cluster meet <host> <port>?命令,可以讓服務器把指定的節(jié)點加入到自己所在的集群中,假設向服務器 A 發(fā)送命令:cluster meet 127.0.0.1 12345,假設監(jiān)聽端口12345 的服務器為B,那么節(jié)點A和節(jié)點B將首先進行?握手?:
槽指派: redis 集群內部,通過分片的方式來保存鍵值數據,每個分片稱之為一個槽(slot),共有0-16383共計16384個槽(2048 * 8); 集群建立后,處于未上線狀態(tài),需要進行槽指派后,才上線并開始提供服務;
集群命令執(zhí)行: 集群中因為數據分片存儲,執(zhí)行命令的過程稍微有一點差異:收到命令后,先對key進行hash映射取得該Key的槽號,然后判斷該槽是否歸自己處理,若是則執(zhí)行命令,否則取得負責該槽的節(jié)點,返回一個MOVED錯誤,并把該節(jié)點信息返回,引導客戶端向正確的節(jié)點請求服務;
- 該槽歸自己處理,進行處理;
- 該槽不歸自己處理,返回一個MOVED錯誤,并把負責處理該槽的節(jié)點信息返回,引導客戶端向正確的節(jié)點請求服務;
- 該槽數據目前正在遷移:
- 首先在自己的庫中查找該鍵,若存在,處理;
- 若不存在,返回ASK錯誤,并給出新節(jié)點信息,引導客戶端向新節(jié)點請求服務;客戶端需要先向新節(jié)點發(fā)送asking命令,再發(fā)送正式的命令,否則將會收到一個moved錯誤
注:正在被導入的槽和數據,不算,只有導入完成后,才會集群內廣播
關于集群的內部結構:
- clusterNode: 表示一個節(jié)點
- clusterLink: 表示一個節(jié)點的連接信息
- clusterState: 每個節(jié)點都保存著一個clusterState,記錄了以當前節(jié)點為視角,集群目前所處的狀態(tài),如是否在線、包含多少節(jié)點、當前配置紀元等等;其中兩個屬性記錄了所有槽指派信息:
- clusterState.slots: char數組,長度2048(16384/8),用每一個二進制位表示一個槽是否歸當前節(jié)點處理,為0表示不歸我管;
- clusterState.numslots:當前節(jié)點負責處理的槽的數量,即slots數組中位的值為1的數量;
- clusterState.nodes:clusterNode結構數組,長度16384
為什么是16384個槽?由記錄槽指派信息的結構可知,其實是2048,redis節(jié)點維護一個長度2048的char數組,用數組元素中的每一位表示一個槽,而char的長度為8位,于是共可以存儲2048*8=16384個槽;
?
參考地址:https://my.oschina.net/u/2407208/blog/3009249
總結
以上是生活随笔為你收集整理的redis 主从 哨兵 集群 及原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: rabbitMq实现延迟队列
- 下一篇: 蓝牙LE Audio的关键-LC3技术