Redis之高可用、集羣、雲平臺搭建(非原創)

    1. 文章大綱

      1、基礎知識學習
      2、Redis常見的幾種架構及優缺點總結
      3、Redis之Redis Sentinel(哨兵)實戰
      4、Redis之Redis Cluster(分佈式集羣)實戰
      5、Java之Jedis鏈接Redis(Redis Cluster版本)
      6、Redis之雲平臺介紹
      7、項目源碼與資料下載
      8、參考文章php

       

      1、基礎知識學習

        Redis的基礎包括如下內容,可參考文章https://www.cnblogs.com/WUXIAOCHANG/p/10832330.html進行學習
      (1)安裝並設置開機自動啓動
      (2)Redis文件結構
      (3)Redis啓動方式
      (4)Redis持久化
      (5)Redis配置文件詳解
      (7)Redis圖形化工具
      (8)Java之Jedis鏈接Redis單機css

      2、Redis常見的幾種架構及優缺點總結

      1. Redis單副本

      Redis單副本,採用單個Redis節點部署架構,沒有備用節點實時同步數據,不提供數據持久化和備份策略,適用於數據可靠性要求不高的純緩存業務場景。html

       

      優勢
      架構簡單,部署方便;
      高性價比:緩存使用時無需備用節點(單實例可用性能夠用supervisor或crontab保證),固然爲了知足業務的高可用性,也能夠犧牲一個備用節點,但同時刻只有一個實例對外提供服務;
      高性能。java

      缺點
      不保證數據的可靠性;
      在緩存使用,進程重啓後,數據丟失,即便有備用的節點解決高可用性,可是仍然不能解決緩存預熱問題,所以不適用於數據可靠性要求高的業務;
      高性能受限於單核CPU的處理能力(Redis是單線程機制),CPU爲主要瓶頸,因此適合操做命令簡單,排序、計算較少的場景。也能夠考慮用Memcached替代。node

      2. Redis多副本(主從)

      Redis多副本,採用主從(replication)部署結構,相較於單副本而言最大的特色就是主從實例間數據實時同步,而且提供數據持久化和備份策略。主從實例部署在不一樣的物理服務器上,根據公司的基礎環境配置,能夠實現同時對外提供服務和讀寫分離策略。git

       

      優勢
      高可靠性:一方面,採用雙機主備架構,可以在主庫出現故障時自動進行主備切換,從庫提高爲主庫提供服務,保證服務平穩運行;另外一方面,開啓數據持久化功能和配置合理的備份策略,能有效的解決數據誤操做和數據異常丟失的問題;
      讀寫分離策略:從節點能夠擴展主庫節點的讀能力,有效應對大併發量的讀操做。github

      缺點
      故障恢復複雜,若是沒有RedisHA系統(須要開發),當主庫節點出現故障時,須要手動將一個從節點晉升爲主節點,同時須要通知業務方變動配置,而且須要讓其它從庫節點去複製新主庫節點,整個過程須要人爲干預,比較繁瑣;
      主庫的寫能力受到單機的限制,能夠考慮分片;
      主庫的存儲能力受到單機的限制,能夠考慮Pika;
      原生複製的弊端在早期的版本中也會比較突出,如:Redis複製中斷後,Slave會發起psync,此時若是同步不成功,則會進行全量同步,主庫執行全量備份的同時可能會形成毫秒或秒級的卡頓;又因爲COW機制,致使極端狀況下的主庫內存溢出,程序異常退出或宕機;主庫節點生成備份文件致使服務器磁盤IO和CPU(壓縮)資源消耗;發送數GB大小的備份文件致使服務器出口帶寬暴增,阻塞請求,建議升級到最新版本。redis

      3. Redis Sentinel(哨兵)

        Redis Sentinel是社區版本推出的原生高可用解決方案,其部署架構主要包括兩部分:Redis Sentinel集羣和Redis數據集羣。
        其中Redis Sentinel集羣是由若干Sentinel節點組成的分佈式集羣,能夠實現故障發現、故障自動轉移、配置中心和客戶端通知。Redis Sentinel的節點數量要知足2n+1(n>=1)的奇數個。算法

       
       

      優勢
      Redis Sentinel集羣部署簡單;
      可以解決Redis主從模式下的高可用切換問題;
      很方便實現Redis數據節點的線形擴展,輕鬆突破Redis自身單線程瓶頸,可極大知足Redis大容量或高性能的業務需求;
      能夠實現一套Sentinel監控一組Redis數據節點或多組數據節點。數據庫

      缺點
      部署相對Redis主從模式要複雜一些,原理理解更繁瑣;
      資源浪費,Redis數據節點中slave節點做爲備份節點不提供服務;
      Redis Sentinel主要是針對Redis數據節點中的主節點的高可用切換,對Redis的數據節點作失敗斷定分爲主觀下線和客觀下線兩種,對於Redis的從節點有對節點作主觀下線操做,並不執行故障轉移。
      不能解決讀寫分離問題,實現起來相對複雜。

      建議
      若是監控同一業務,能夠選擇一套Sentinel集羣監控多組Redis數據節點的方案,反之選擇一套Sentinel監控一組Redis數據節點的方案。
      sentinel monitor <master-name> <ip> <port> <quorum> 配置中的<quorum>建議設置成Sentinel節點的一半加1,當Sentinel部署在多個IDC的時候,單個IDC部署的Sentinel數量不建議超過(Sentinel數量 – quorum)。
      合理設置參數,防止誤切,控制切換靈敏度控制:
      a. quorum
      b. down-after-milliseconds 30000
      c. failover-timeout 180000
      d. maxclient
      e. timeout

      部署的各個節點服務器時間儘可能要同步,不然日誌的時序性會混亂。
      Redis建議使用pipeline和multi-keys操做,減小RTT次數,提升請求效率。
      自行搞定配置中心(zookeeper),方便客戶端對實例的連接訪問。

      4. Redis Cluster

        Redis Cluster是社區版推出的Redis分佈式集羣解決方案,主要解決Redis分佈式方面的需求,好比,當遇到單機內存,併發和流量等瓶頸的時候,Redis Cluster能起到很好的負載均衡的目的。
        Redis Cluster集羣節點最小配置6個節點以上(3主3從),其中主節點提供讀寫操做,從節點做爲備用節點,不提供請求,只做爲故障轉移使用。
        Redis Cluster採用虛擬槽分區,全部的鍵根據哈希函數映射到0~16383個整數槽內,每一個節點負責維護一部分槽以及槽所印映射的鍵值數據。

       

      優勢
      無中心架構;
      數據按照slot存儲分佈在多個節點,節點間數據共享,可動態調整數據分佈;
      可擴展性:可線性擴展到1000多個節點,節點可動態添加或刪除;
      高可用性:部分節點不可用時,集羣仍可用。經過增長Slave作standby數據副本,可以實現故障自動failover,節點之間經過gossip協議交換狀態信息,用投票機制完成Slave到Master的角色提高;
      下降運維成本,提升系統的擴展性和可用性。

      缺點
      Client實現複雜,驅動要求實現Smart Client,緩存slots mapping信息並及時更新,提升了開發難度,客戶端的不成熟影響業務的穩定性。目前僅JedisCluster相對成熟,異常處理部分還不完善,好比常見的「max redirect exception」。
      節點會由於某些緣由發生阻塞(阻塞時間大於clutser-node-timeout),被判斷下線,這種failover是沒有必要的。
      數據經過異步複製,不保證數據的強一致性。
      多個業務使用同一套集羣時,沒法根據統計區分冷熱數據,資源隔離性較差,容易出現相互影響的狀況。
      Slave在集羣中充當「冷備」,不能緩解讀壓力,固然能夠經過SDK的合理設計來提升Slave資源的利用率。
      Key批量操做限制,如使用mset、mget目前只支持具備相同slot值的Key執行批量操做。對於映射爲不一樣slot值的Key因爲Keys不支持跨slot查詢,因此執行mset、mget、sunion等操做支持不友好。
      Key事務操做支持有限,只支持多key在同一節點上的事務操做,當多個Key分佈於不一樣的節點上時沒法使用事務功能。
      Key做爲數據分區的最小粒度,不能將一個很大的鍵值對象如hash、list等映射到不一樣的節點。
      不支持多數據庫空間,單機下的redis能夠支持到16個數據庫,集羣模式下只能使用1個數據庫空間,即db 0。
      複製結構只支持一層,從節點只能複製主節點,不支持嵌套樹狀複製結構。
      避免產生hot-key,致使主庫節點成爲系統的短板。
      避免產生big-key,致使網卡撐爆、慢查詢等。
      重試時間應該大於cluster-node-time時間。
      Redis Cluster不建議使用pipeline和multi-keys操做,減小max redirect產生的場景。

      5. Redis自研

      Redis自研的高可用解決方案,主要體如今配置中心、故障探測和failover的處理機制上,一般須要根據企業業務的實際線上環境來定製化。

       
       

      優勢
      高可靠性、高可用性;
      自主可控性高;
      貼切業務實際需求,可縮性好,兼容性好。

      缺點
      實現複雜,開發成本高;
      須要創建配套的周邊設施,如監控,域名服務,存儲元數據信息的數據庫等;
      維護成本高。

      3、Redis之Redis Sentinel(哨兵)實戰

      1. 實戰的項目架構

        採用一主(MASTER)二從(SLAVE)三哨兵(SENTINEL)的架構

      2. 將下載的Redis複製3分,分別命名以下:

       

      3. 修改三個Reids的配置文件

      3.1 配置主從

      (1)master_6379文件夾中redis.windows.conf文件配置

      port 6379

      (2)slave_6380文件夾中redis.windows.conf文件配置

      port 6380 slaveof 127.0.0.1 6379 

      (3)slave_6381文件夾中redis.windows.conf文件配置

      port 6381 slaveof 127.0.0.1 6379 

      3.2 哨兵配置
      每個redis目錄中都建立一個文sentinel.conf文件
      master_6379的sentinel.conf文件配置以下

      #當前Sentinel服務運行的端口 port 26379 #master #Sentinel去監視一個名爲mymaster的主redis實例,這個主實例的IP地址爲本機地址127.0.0.1,端口號爲6379, #而將這個主實例判斷爲失效至少須要2個 Sentinel進程的贊成,只要贊成Sentinel的數量不達標,自動failover就不會執行 sentinel monitor mymaster 127.0.0.1 6379 1 #指定了Sentinel認爲Redis實例已經失效所需的毫秒數。當 實例超過該時間沒有返回PING,或者直接返回錯誤,那麼Sentinel將這個實例標記爲主觀下線。 #只有一個 Sentinel進程將實例標記爲主觀下線並不必定會引發實例的自動故障遷移:只有在足夠數量的Sentinel都將一個實例標記爲主觀下線以後,實例纔會被標記爲客觀下線,這時自動故障遷移纔會執行 sentinel down-after-milliseconds mymaster 5000 #指定了在執行故障轉移時,最多能夠有多少個從Redis實例在同步新的主實例,在從Redis實例較多的狀況下這個數字越小,同步的時間越長,完成故障轉移所需的時間就越長 sentinel config-epoch mymaster 12 #若是在該時間(ms)內未能完成failover操做,則認爲該failover失敗 sentinel leader-epoch mymaster 13 

      slave_6380中的sentinel.conf文件配置

      #當前Sentine2服務運行的端口 port 26479 #slave1 sentinel monitor mymaster 127.0.0.1 6379 1 sentinel down-after-milliseconds mymaster 5000 sentinel config-epoch mymaster 12 sentinel leader-epoch mymaster 13 

      slave_6381中的sentinel.conf文件配置

      #當前Sentine3服務運行的端口 port 26579 #slave2 sentinel monitor mymaster 127.0.0.1 6379 1 sentinel down-after-milliseconds mymaster 5000 sentinel config-epoch mymaster 12 sentinel leader-epoch mymaster 13 

      4. 啓動服務

      編寫啓動redis腳本
      編寫一個 bat 來啓動 redis,在每一個節點目錄下創建 startup.bat,內容以下:

      title master_6379 redis-server.exe redis.windows.conf 

      舒適提示:
      (1)title後名稱需與Reids文件夾名稱一致
      (2)能夠直接運行startup.bat來啓動redis,也能夠在redis安裝目錄下用命令redis-server.exe redis.windows.conf直接啓動

      編寫sentinel啓動腳本
      編寫一個 bat 來啓動 sentinel,在每一個節點目錄下創建 startup_sentinel.bat,內容以下:

      title master_6379 redis-server.exe sentinel.conf --sentinel 

      舒適提示:
      (1) title命名規則 redis文件夾名, 注意「--sentinel」不是註釋,必須存在
      (2) 另外啓動sentinel還能夠在redis安裝目錄下用命令redis-sentinel sentinel.conf 來啓動

      5. Redis服務啓動成功

      master 6379

       

      slave 6380

       

      slave 6381

       

      6. sentinel服務啓動成功

      sentinel 26379

       

      sentinel 26479

       

      sentinel 26579

       

      7. 服務查看

      7.1 查看redis服務狀態,命令: info replication
      master 6379

       

      slave 6380

       

      slave 6381

       

      7.2 查看sentinel的狀態,命令: info sentinel

       

      8. redis主從自動failover測試

      中止master服務器,查看剩餘服務器的狀態
      slave 6380

       

      slave 6381

       

      從上圖中能夠看出來,master的服務器端口從6379變成了6380,也就是說redis自動的實現了主從切換,
      咱們能夠在查看下sentinel的狀態,以下:

       

      咱們發現sentinel監控到127.0.0.1:6379已經沒法ping通了,切換master服務器爲127.0.0.1:6380

      舒適提示:在實際操做中,不必定master爲6380,多是6381,具體看當時執行策略。

      4、Redis之Redis Cluster(分佈式集羣)實戰

      1. 實戰的項目架構

      (1)3個主節點,建議配置3個從節點,其他3個做爲各個主節點的從節點(也是官網推薦的模式),因此須要6臺虛擬機。主節點崩潰,從節點的Redis就會提高爲主節點,代替原來的主節點工做,崩潰的主Redis恢復工做後,會再成爲從節點
      (2)集羣
      (3)主從複製
      (4)哨兵模式
      (5)分片

      2. 所需軟件

      (1)Redis
      (2)Ruby語言運行環境
      (3)Redis的Ruby驅動redis-xxxx.gem
      (4)建立Redis集羣的工具redis-trib.rb

      3. 下載Redis並建立相應集羣目錄

        把 redis 解壓後,再複製出 5 份,配置 三主三從集羣。 因爲 redis 默認端口號爲 6379,那麼其它5份的端口能夠爲6380,6381,6382,6383,6384。 而且把目錄使用端口號命名

       

      4. 修改配置文件

      打開每一個Redis目錄下的文件 redis.windows.conf,修改裏面的端口號分別對應相對應的文件夾名:637九、6380、638一、638二、638三、6384,再修改集羣支持配置,將如下配置前面的#去掉。

       
      cluster-enabled yes cluster-config-file nodes-6379.conf cluster-node-timeout 15000 appendonly yes 

      cluster-config-file nodes-6379.conf 是爲該節點的配置信息,這裏使用 nodes-端口.conf命名方法。服務啓動後會在目錄生成該文件(爲cluster-config-file nodes-文件夾名字.conf)

      編寫啓動腳本,或者進入每一個端口命名的文件夾下啓動服務,具體能夠參考第三的內容
      編寫一個 bat 來啓動 redis,在每一個節點目錄下創建 startup.bat,內容以下:

      title redis-6379 redis-server.exe redis.windows.conf 

      舒適提示:title後面爲文件夾名稱

      5. 安裝Ruby

      redis的集羣使用 ruby腳本編寫,因此係統須要有 Ruby 環境 ,下載地址
      https://rubyinstaller.org/downloads/

       
       

      安裝時3個選項都勾選。

      6. 安裝Redis的Ruby驅動redis-xxxx.gem

      下載地址 :https://rubygems.org/pages/download

       

        下載後解壓,當前目錄切換到解壓目錄中,如 D:\Program Files\Redis_cluster\rubygems-2.7.7 而後命令行執行 ruby setup.rb
        再用 GEM 安裝 Redis :切換到redis安裝目錄,須要在命令行中,執行 gem install redis

       

      7. 安裝集羣腳本redis-trib

        下載地址 https://raw.githubusercontent.com/antirez/redis/unstable/src/redis-trib.rb
         打開該連接把裏面的腳本保存爲redis-trib.rb,建議保存到一個Redis的目錄下(不用每一個都放),例如放到6379目錄下。

      舒適提示:如今打開這個連接中的代碼已不支持redis 5.0如下的版本了,由於redis5.0以上再也不須要redis-trib.rb了,而是使用自帶的redis-cli做爲建立集羣的命令了,老版本的redis-trib.rb可在文章的項目源碼與參考資料中進行下載

      8. 啓動每一個節點而且執行集羣構建腳本

      把每一個節點下的 start.bat雙擊啓動, 在切換到存放了redis-trib.rb的redis目錄在命令行中執行如下內容:

      redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 

      舒適提示:
      (1)--replicas 1 表示每一個主數據庫擁有從數據庫個數爲1。master節點不能少於3個,因此咱們用了6個redis
      (2)三個主從之間的對應關係由策略進行決定,不必定是6379是主,6380是它的從,可是分配完以後,會有三主三從
      (3)若是出現 redis-trib.rb is not longer available! 若是redis版本是5.0以上,則使用以下命令:

      redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1 

      (4) 集羣命令建立一次後,之後都不須要再次執行,就算服務器重啓都不須要,集羣伸縮應該須要

      在出現 Can I set the above configuration? (type 'yes' to accept): 請肯定並輸入 yes 。成功後的結果以下:

       
       

      9. 鏈接集羣進行測試

      使用Redis客戶端Redis-cli.exe來查看數據記錄數,以及集羣相關信息
      命令:redis-cli –c –h 」地址」 –p "端口號" ; c 表示集羣

       

      查看集羣的信息,命令:cluster info

       

      查看主從關係,命令: info replication

       

      主庫顯示信息:
       

      從庫顯示信息:

       

      查看各個節點分配slot,命令 cluster nodes

       

      能夠看到有3個master,3個slave
      以及能夠看到master各自的slot分佈狀況

      10. Redis集羣數據分配策略

      採用一種叫作哈希槽 (hash slot)的方式來分配數據,redis cluster 默認分配了 16384 個slot,當咱們set一個key 時,會用CRC16算法來取模獲得所屬的slot,而後將這個key分到哈希槽區間的節點上,具體算法就是:CRC16(key) % 16384
      注意的是:必需要3個以上的主節點,不然在建立集羣時會失敗,三個節點分別承擔的slot 區間是:
      節點A覆蓋0-5460;
      節點B覆蓋5461-10922;
      節點C覆蓋10923-16383.

      5、Java之Jedis鏈接Redis(Redis Cluster版本)

      1. 使用idea新建maven項目

       
       
       
       

      建立後的項目結構以下:

       

      2. pom.xml文件添加jar包依賴

      <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wxc</groupId> <artifactId>com-redis2</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!--添加測試依賴--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!--添加redis依賴--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.7.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.3.2</version> </dependency> </dependencies> </project> 

      3. 新建JedisclusterTest.java進行集羣鏈接測試

      package com.wxc.redis; import org.junit.Test; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.JedisCluster; import redis.clients.jedis.JedisPoolConfig; import java.io.IOException; import java.util.HashSet; import java.util.Set; public class JedisclusterTest { //鏈接redis集羣 @Test public void testJedisCluster() throws Exception { //建立一個JedisCluster對象 Set<HostAndPort> nodes = new HashSet<HostAndPort>(); nodes.add(new HostAndPort("127.0.0.1", 6379)); nodes.add(new HostAndPort("127.0.0.1", 6380)); nodes.add(new HostAndPort("127.0.0.1", 6381)); nodes.add(new HostAndPort("127.0.0.1", 6382)); nodes.add(new HostAndPort("127.0.0.1", 6383)); nodes.add(new HostAndPort("127.0.0.1", 6384)); System.out.println("開始鏈接redis集羣"); //在nodes中指定每一個節點的地址 //jedisCluster在系統中是單例的。 JedisCluster jedisCluster = new JedisCluster(nodes); System.out.println("初始化數據"); jedisCluster.set("name2", "zhangsan"); jedisCluster.set("value2", "100"); String name = jedisCluster.get("name"); String value = jedisCluster.get("value"); System.out.println(name); System.out.println(value); //系統關閉時關閉jedisCluster jedisCluster.close(); } } 

      4. 運行項目

       

      5. 測試集羣故障轉移與主從備份

      5.1 查看主從關係

       

      從圖中咱們能夠看出,6379,6381,6383是主節點,其餘是從節點

      5.2 測試故障自動轉移
      如今咱們將6381的服務斷開,以後再查看一次服務

       

      咱們能夠看到這兩個服務已經掛了,以後咱們再次運行java項目,此次咱們把key改成name三、value3

       

      再次運行java項目

       

      能夠看到集羣數據操做成功

      5.3 查看集羣自動主從備份
      如今咱們用Redis客戶端工具打開鏈接,進行數據查看,咱們能夠看到name3和value3都插入成功了

       

      剛剛咱們的6381服務是關閉的,咱們如今從新打開,再看看6381數據是否會自動同步

       

      打開以後,咱們發現其數據已經自動同步

      7、項目源碼與資料下載

      連接:https://pan.baidu.com/s/1wcWcXO-qEFfVb9ujcjRvMA
      提取碼:pe01

      8、參考文章

      1. http://database.ctocio.com.cn/239/14564239.shtml
      2. https://blog.csdn.net/weixin_41846320/article/details/83654766
      3. https://blog.csdn.net/weixin_41846320/article/details/83753182
相關文章
相關標籤/搜索