redis主從架構,分片集羣詳解

寫在前面

這邊文章的排版時後面補的,因此看起來不太光鮮亮麗,忘周知。node

:這篇筆記有點長,若是你認真看完,收穫會很多,若是你只是忘記了相關命令,請翻到末尾。c++

redis的簡單介紹:

  一個提供多種數據類類型儲存,整個系統都在內存中運行的,redis

  按期經過異步的方式把數據刷到磁盤進行保存的一個內存數據庫數據庫

  由於實在內存中操做數據,因此效率很是高,但受制於物理內存的限制,通常用做處理少許數據的高性能操做;編程

Redis的單機搭建

  首先安裝依賴:緩存

yum -y install cpp binutils glibc glibc-kernheaders glibc-common glibc-devel gcc make gcc-c++ libstdc++-devel tclruby

  建立文件夾,將rediss上傳到該文件夾內,並進行解壓:服務器

tar -xvf redis-3.0.2.tar.gz網絡

  得到解壓文件架構

 img

  進入到解壓文件 進行先編譯 , 而後安裝 :

make (編譯) , make install (安裝)

  把配置文件複製一份到上一級目錄(以配置文件驅動redis,完成多個redis服務的啓動):

 img

  感受那個壓縮包有點扎眼睛,心狠手辣的刪掉它,如今編程這樣

 img

  準備後臺啓動redis,修改配置文件 redis .conf以下所示,保存後退出:

 img

  啓動redis,由於是後臺啓動,因此沒什麼反應,咱們查詢進程看看是否啓動:

 img

  咱們運行客戶端測試一把,是否 ping 通: redis-cli

 img

好!上面已經將 redis 安裝到了咱們的服務器,下面開始搭建 redis的主從複製(讀寫分離):

Redis的主從複製搭建

首先說說主從複製的好處是什麼:

  • 避免單點故障,預防一個redis掛掉後,redis插槽有空擋,致使集羣不可用

  • 構建讀寫分離架構,知足讀多寫少的的場景(數據庫80%的操做都是在讀取,這句話是誰說的?)

Redis主從環境搭建

開始操做,咱們須要啓動三臺 redis 服務,完成主從架構:

  redis 默認的端口爲6379 ,咱們建立三個目錄,放着三個配置文件,分別表明不一樣的端口:

  並把配置文件分別複製進這三個端口所表明的目錄:

    

  而後分別修改三個文件夾中的配置文件,咱們把6379端口的 redis 服務設爲 主,其餘兩個爲從

    

    

  而後以配置文件方式 依次啓動三個 redis 服務:

    

  啓動客戶端分別對三個服務進行測試:

    

  設置主從關係一共有兩種方式,:

  • 第一種爲在 redis.conf 中配置 ,永久生效 slaveof <主ip> <主端口>

  • 第二種爲在redis-cli 中鍵入,重啓服務失效 slaveof <主ip> <主端口>

  今天咱們測試採用第二種,由於後面還有其餘的演示,生產環境下應該使用第一種 永久性配置

   咱們以6379 作爲主 其餘兩個做爲從,完成一下操做

    

    

   登陸 6379 的客戶端 查看主從信息:

    

   在主庫寫入和讀取數據測試:

    

   咱們把數據存放到了 端口爲6379 的主庫,作了主從,咱們就能在從庫中把數據拿出來

      

  上面咱們演示了 主從架構,下面咱們演示,主從從架構(鏈式主從)

    使用 kill -9 命令殺死剛剛我啓動的三個 redis 服務,取消剛剛創建的暫時的主從關係:

     下面咱們創建 6381以 6380 爲主,6380 以 6379 爲主的鏈式主從從架構

        6381 ——> 6780 ——> 6379

  重啓服務後,開始搭建咱們的主從從架構:

   還記得咱們剛剛搭建主從的命令嗎? slaveof <主ip> <主端口>

    6381 以6380 爲主:

     

    6380 以 6379 爲主 :

     

    咱們來到 6379 主庫查看 主從信息

     

    隨後咱們再來到6380,看看主從狀況:

     

    最後一個6381,做爲從庫,咱們就不看了,下面咱們再6379 中存取的讀取數據測試 (沒毛病)

     

    默認狀況下從庫是不能寫入輸入的,如要要開啓須要配置文件中開啓,非只讀:

       slave-read-only no

Redis主從複製,數據一致性原理

說說原理:爲何咱們創建主從架構後,在主庫中的數據 能夠在從庫中獲取呢?   

  • 當從庫和主庫創建MS關係後,從庫會向主數據庫發送PSYNC命令;

  • 主庫接收到PSYNC命令後會開始在後臺保存快照(RDB),並緩存該期間的命令;

  • 當快照完成後,主Redis會將快照文件和全部緩存的寫命令發送給從Redis;

  • 從Redis接收到後,會載入快照文件而且執行收到的緩存的命令;

  • 以後,主Redis每當接收到寫命令時就會將命令發送從Redis,從而保證數據的一致;

注意:數據是持久化到磁盤,從庫redis 加載數據,完成數據同步,中間涉及到磁盤IO

如今能夠經過開啓無磁盤複製完成數據同步 : repl-diskless-sync yes

原理是不持久化數據到磁盤,直接經過網絡發送給 從redis,避免IO性能差(還在測試階段,不穩定)      

常見問題:服務宕機 處理手段:

  • 若是是從庫redis 宕機,直接重啓,會自動加入主從架構,並自動經過增量複製完成數據同步

  • 若是是主庫宕機:選擇一個從庫斷掉主從關係,並將自身提高爲主庫提供服務 : SLAVEOF NO ONE

  • 重啓掛掉的服務,經過 SLAVEOF ip port 將其設置爲其餘從庫的從庫,保持主從架構

哨兵機制

在上面的主從架構中,主服務宕機沒咱們得手動重啓並加入,這就顯得很麻煩,redis有個哨兵機制,能夠自動應對上述狀況:

  哨兵的主要做用:監控redis服務是否正常運行,若是 主reids 宕機,在從庫中選取 leader 當新的主庫:

  單個哨兵的監控:只監控 master ,自動發現master 下的 slave

  多個哨兵的監控:在監控master時,還會互相監督;

  下面來看看一主多從下 哨兵的表現:

     以 6379 爲主 6380 6381 均爲 6379 的從,在剛剛的環境下 只需修改6381 從新綁定6379 爲主便可:

     

    進入redis 的解壓目錄 編輯 sentinel.conf 配置文件,追加一個配置 :sentinel monitor MyMaster 127.0.0.1 6379 1

     

    解釋: MyMster : 自定義監聽主數據的名稱

       127.0.0.1:監控主數據的 IP

        6379 :監控主數據的 port

        1   : 最低經過票數     

   配置完成後,啓動哨兵: redis-sentinel ./sentinel.conf

     

   接下來,咱們先讓從庫 6381 宕機,觀察哨兵反應如何

     我估計 +sdown 爲shutdown的意思 關閉

    

   咱們重啓 6381 ,看哨兵反應: reboot : 從新啓動 | conver -to slave :使其轉變爲從庫

    

   從庫已經試過了,咱們再來試試主庫宕機會怎麼樣:    img

   而後咱們重啓 6379,看看反應:    img

   能夠看到 6379 和 6381 都已經成爲了 6380 的從庫,自動完成主從架構

    

好了,哨兵也就講到這兒了,下面來架設redis3.0 的自帶的分片集羣。

Redis3.0的分片集羣

環境搭建前的清道夫

    全部redis節點互聯,超過半數以上的節點檢測爲失效,才確認爲失效,客戶端隨意鏈接一個redis便可

    參與集羣的redis 分攤 16384 個插槽

  首先。咱們把剛剛搭建的全部redis的服務所有 kill 掉,

  刪除RDB持久化文件,搭建集羣時,全部的 redis 均無數據,爲空的

    

  進入三個 redis 修改配置文件: 注意改端口,隨後啓動啓動所有redis 服務

    

  除了點小意味,啓動報錯不能再slaveof 下開啓集羣 我把配置文件刪掉從新刷了一份,

  按理說我關閉服務後 ,主從架構應該消失啊,可是我在建立集羣時,主從架構還在,

    因此配置文件: 修改端口——開啓後臺啓動——開啓集羣—— 開啓並修改集羣配置文件後啓動:

     

    由於咱們開啓集羣的配置文件,因此如今目錄是這樣的了

      

    接下來安裝 ruby 環境: yum -y install zlib ruby rubygems

    rz上傳 redis-3.2.1.gem: gem install -l redis-3.2.1.gem

 集羣環境搭建

  • 進入到 redis 的解壓目錄:ll /usr/src/redis/redis-3.0.2/src/

  • ./redis-trib.rb create --replicas 0 192.168.41.130:6379 192.168.41.130:6380 192.168.41.130:6381

    • replicas 0 : 表示從庫數量爲 0

    • 後面跟三個要加入集羣的機器的 IP Port

  • 注意:ifconfig 查看虛擬機的 ip 這裏不能使用127.0.0.1 ,不然 jedis 客戶端鏈接不上

建立集羣:        img

插入數據和獲取數據測試:

提示:如今咱們不能再使用 redis-cli 來插入數據,由於集羣的每一個 redis 都有本身的插槽值,

當咱們插入一個數據時,不知道 key 的 hash 值是多少,可能該key對應的hash槽不在此區間

咱們的6379 的插槽數區間爲 0-5460 ,而 abc 的 hash對應的槽所在的redis 應該爲 6380 ( 列子)

          

咱們再去6380,插入這條數據,就能成功,可是這樣顯得就很搓了,

使用 redis-cli -p 6379 -c 鏈接集羣中的6379端口的機器, c: cluster

存入值的時候,自動爲咱們重定向了 redis

          

咱們登陸6381 客戶端 redis-cli -p 6381 -c 獲取數據,也是給我嗎自動定向到了6380:

如今能夠隨意插入和獲取數據了

          

要吃飯了,先擱置一下,吃完飯再續,好了,睡覺以前把它總結完。

下面咱們來查看集羣信息,隨便選取一個節點,經過 : cluster nodes

      img

其中顯示的信息有每一個節點的 id , redis的ip port 和身份,鏈接數,插槽區間;

當咱們往集羣中插入一條數據時,執行流程爲:

  • 首先計算出 key 的插槽值,計算出hash值對 16384取餘,獲得插槽值

  • 而後根據插槽值找到對應的 redis 節點,

  • 定向到高節點執行插入的命令;

  • 整個集羣包含16384個插槽點,被 ./redis-trib.rb 腳本均分給參加集羣的 機器節點

Redis的節點的增刪

集羣環境咱們已經搭建好了,下面咱們來實現 redis 節點的 增 刪:

  增長節點:

咱們再建立一個 6382 端口的redis 服務,

主要修改配置文件中的 :開啓後臺啓動,修改端口,打開集羣,打開並修改 集羣配置文件,直接啓動

    

進入redis的解壓文件 src/,執行腳本,指定加入集羣的隨便一個節點的 ip 和 port 便可

cd /usr/src/redis/redis-3.0.2/src/

執行腳本 : ./redis-trib.rb add-node 192.168.41.130:6382 192.168.41.130:6379

第一個 IP port 爲要加入集羣的redis 的IP和port 第二個爲已在集羣中的隨意一臺機器的 IP和port

    

咱們再次查看集羣信息:隨便選取一個節點

 img

集羣雖然已經加入,可是並無自動分配插槽給該節點,咱們手動從其餘節點(6379) ,劃分一點過來

./redis-trib.rb reshard 192.168.41.130:6381(沒截到圖,用的資料上的圖)

給定要分配的插槽數就,好比給 1000

輸入接受高插槽數的一個redis 的節點ID

      

而後經過其餘隨意一個節點查看集羣信息: cluster nodes

總結步驟:

  • 啓動服務——> 使用 redis-trib.rb add-node 添加到集羣 ——> 分配插槽redis-trib.rb reshard

刪除節點:

  • 刪除一個節點首先就得把它全部的節點撥給其餘的節點,好比咱們要刪除 6382 節點

  • 咱們就應該把 6382節點上的插槽 撥出去 列子中咱們撥給 6381,最後必須採用done 類型撥出去

      

  • 而後咱們觀察集羣的相關信息: 6382 沒有插槽點了

        

  • 刪除節點:./redis-trib.rb del-node 192.168.41.130:6380 ac7bc0b959dcd7a588d573d5ee8b78ab39368d0b

    • 格式爲:del-onde ip :port node_id

  • 查看集羣節點信息:發現6382節點已經被咱們刪除了

        

集羣到這裏就結束了,可是離咱們的高併發和高可用還有一截路,下面咱們來講說:

  一、 集羣中的每一個節點都會按期的向其它節點發送PING命令,而且經過有沒有收到回覆判斷目標節點是否下線;

  二、 集羣中每一秒就會隨機選擇5個節點,而後選擇其中最久沒有響應的節點放PING命令;

  三、 若是必定時間內目標節點都沒有響應,那麼該節點就認爲目標節點疑似下線

  四、 當集羣中的節點超過半數認爲該目標節點疑似下線,那麼該節點就會被標記爲下線**(fail)**;

  五、 當集羣中的任何一個節點下線,就會致使插槽區有空檔,不完整,那麼該集羣將不可用;

  六、 如何解決上述問題?

    a) 在Redis集羣中可使用主從模式實現某一個節點的高可用

    b) 當該節點(master)宕機後,集羣會將該節點的從數據庫(slave)轉變爲(master)繼續完成集羣服務;

集羣+主從=高可用、高性能、高併發

下面引出 「集羣下的主從複製」,三臺master搭建集羣,分別爲每一臺master 作一個主從架構,6臺服務

6379,6380,6381 爲主 ,搭建集羣

6382,6383,6384 爲從,你們主從

    

2019年4月17日 00:13:51 先休息了,明天補完....

 開始搭建集羣架構:

  • ./redis-trib.rb create --replicas 1 192.168.41.130:6379 192.168.41.130:6380 192.168.41.130:6381 192.168.41.130:6382 192.168.41.130:6383 192.168.41.130:6384

    • 1:表明從庫數量爲1

    • 前三個 IP port : 依次爲構建集羣的三臺機器的 IP port

    • 後三個 IP port : 依次爲爲前面機器搭建主從的機器的 IP port

而後我就報錯了,以下所示:

     

  • 這個問題來自於:你從新創建集羣,可是你的 rdb持久化文件 以及 node-xxx.conf 沒有刪除乾淨,

  • 若是還不行,登陸後刷一下數據 : flushdb

  • 再次執行搭建主從集羣:

     

  • 查看集羣信息 : cluster nodes

    

  • 接下來用數聽說話:

    

  • 運行一切正常,下面但是測試 該環境下的高可用性:

若是從庫宕機 (6384),看效果:

      

咱們再次獲取數據,觀察集羣是否可用:

      

咱們重啓掛掉的從庫機器: 自動加入集羣中的主從架構

      

下面咱們測試 主庫宕機(6380),觀察變化:

      鏈接被拒絕 ???

        

      我換一個機器試試:由於6380端口機器被掛掉了,我剛剛實在6380鍵入命令,因此失效

        

上面能夠看出,6380 (Master)是 fail 狀態,可是咱們依舊可以獲取到數據,集羣可用;

你再看看 是否是除了 6380 宕機的Master 外,好像 6383 也是Master 了?

由於Master (6380 ) 對應的 從庫就是 Slave (6383),當主庫掛掉後,提高從庫爲主庫,繼續對外提供服務,

下面,咱們重啓掛掉的 6380,看看它是否會造反?

        

        

能夠看出 6380,在通過一番宕機重啓後,已經變爲6383的從庫,繼續加入集羣保持主從架構;

  集羣到這裏也說完了,下面說說 在這個過程當中經常使用的命令。

經常使用命令

  • redis-server ./xxx/redis.conf  : 以配置文件啓動 redis 服務

  • redis-cli -p 6379        : 啓動 redis 客戶端,鏈接6379 服務

  • redis-cli -p 6379 -c       : 啓動 redis 客戶端,鏈接在集羣中的 6379 服務

  • info plication         : 查看當前節點的信息,角色? 主庫與從庫相關信息

  • cluster nodes         : 在集羣環境某個節點中使用,查看當前集羣的機器信息

  • slaveof <master Ip><Master Port> : 暫時創建主從關係,在配置文件可長久配置 (生產環境都是長久配置)  

  • ./redis-trib.rb create --replicas 0 ip:port ip:port ip:port :建立集羣 從庫爲0

  • ./redis-trib.rb create --replicas 1 ip:port ip:port ip:port ip:port ip:port ip:port :集羣+主從

  • ./redis-trib.rb add-node <new-node_IP :port> 集羣服務機器_ip:port : 爲集羣添加 節點  

  • ./redis-trib.rb del-node <ip : port> node_id  : 集羣下刪除某個節點,須要吧插槽撥出去

  • kill -9 server_id        : 殺死 Server_id 的服務進程 

  • ps auxf|grep redis |grep -v grep|xargs kill -9 : 殺死全部與 redis 相關的進程服務

基本上就是這些了吧,終於快寫完了!!!

  使用集羣注意:  

    多鍵的命令操做(如MGET、MSET),若是每一個鍵都位於同一個節點,則能夠正常支持,不然會提示錯誤。

    集羣中的節點只能使用0號數據庫,若是執行SELECT切換數據庫會提示錯誤。

相關文章
相關標籤/搜索