Redis Cluster集群搭建與應用

来源:https://www.cnblogs.com/wlandwl/archive/2018/01/25/rediscluster.html
-Advertisement-
Play Games

1.redis-cluster設計 Redis集群搭建的方式有多種,例如使用zookeeper,但從redis 3.0之後版本支持redis-cluster集群,redis-cluster採用無中心結構,每個節點保存數據和整個集群狀態,每個節點都和其他所有節點連接。其redis-cluster架構圖 ...


1.redis-cluster設計

    Redis集群搭建的方式有多種,例如使用zookeeper,但從redis 3.0之後版本支持redis-cluster集群,redis-cluster採用無中心結構,每個節點保存數據和整個集群狀態,每個節點都和其他所有節點連接。其redis-cluster架構圖如下:

其結構特點

  1. 所有的redis節點彼此互聯(PING-PONG機制),內部使用二進位協議優化傳輸速度和帶寬。
  2. 節點的fail是通過集群中超過半數的節點檢測失效時才生效。
  3. 客戶端與redis節點直連,不需要中間proxy層.客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可。
  4. redis-cluster把所有的物理節點映射到[0-16383]slot上(不一定是平均分配),cluster 負責維護node<->slot<->value。
  5. Redis集群預分好16384個桶,當需要在 Redis 集群中放置一個 key-value 時,根據 CRC16(key) mod 16384的值,決定將一個key放到哪個桶中。

redis cluster節點分配

    例如分配三個主節點分別是:7000, 7001, 7002。三個從節點分別是7003,7004,7005。它們可以是一臺機器上的六個埠,也可以是六台不同的伺服器。採用哈希槽 (hash slot)的方式來分配16384個slot 的話,六個節點分別承擔的slot 區間如同所示:

    

    獲取數據: 如果存入一個值,按照redis cluster哈希槽的演算法: CRC16('key')%16384 = 6782。 就會把這個key 的存儲分配到7001 上了。同樣,當連接(7000,7001,7002)任何一個節點想獲取'key'這個key時,也會這樣的演算法,然後內部跳轉到7001節點上獲取數據 。

 2.redis-cluster主從模式

    redis cluster為了保證數據的高可用性,加入了主從模式,一個主節點對應一個或多個從節點,主節點提供數據存取,從節點則是從主節點拉取數據備份,當這個主節點掛掉後,就會有這個從節點選取一個來充當主節點,從而保證集群不會掛掉。主從模式具有如下特點:

  1. 集群有7000,7001,7002三個主節點, 如果這3個節點都沒有加入從節點,如果7001掛掉了,就無法訪問整個集群,7000和7002的slot也無法訪問。
  2. 主從節點同時掛掉後,如節點7001和7004同時掛了,Redis集群將無法繼續正確地提供服務。
  3. 為每個主節點設置從節點, 比如像這樣, 集群包含主節點7000,7001,7002 以及從節點7003,7004,7005, 那麼即使7001掛掉系統也可以繼續正確工作。7004節點替代了7001節點,所以Redis集群將會選擇7004節點作為新的主節點,集群將會繼續正確地提供服務。 當7001重新開啟後,它就會變成7004的從節點。

2.redis-cluster集群搭建

搭建環境

    本次測試採用虛擬機模式,在本機上做測試,虛擬機環境為Centos7.0。搭建集群需要如下相關依賴軟體,下載地址為“

  1. rubygems軟體包下載:https://rubygems.org/pages/download
  2. ruby軟體包下載:http://www.ruby-lang.org/en/downloads/ 
  3. redis-3.2.2.gem依賴包下載:https://rubygems.global.ssl.fastly.net/gems/redis-3.2.2.gem
  4. openssl軟體包下載: http://www.openssl.org/source/

    下載文件包截圖如下:

     

   redis集群與大多數分散式中間件一樣,redis的cluster也是依賴選舉演算法來保證集群的高可用,所以類似zookeeper一樣,一般是奇數個節點(可以允許N/2以下的節點失效),再考慮到每個節點做Master-Slave互為備份,所以一個redis cluster集群最少也得6個節點。

步驟1:安裝redis

    下載最新版redis並安裝在linux系統中。具體操作可參考網址:Redis介紹及Jedis基礎操作

步驟2:新建集群文件夾目錄

    新建一個根目錄data/cluster/。併在cluster目錄下麵建立6個子目錄:mkdir 7000 7001 7002 7003 7004 7005。

步驟3:修改redis.conf配置文件

   修改redis的配置文件redis.conf,複製原有解壓redis文件中的redis.conf文件到7000目錄中,操作指令如:cp /usr/software/redis-4.0.6/redis.conf /data/cluster/7000。修改redis.conf文件中的配置欄位,修改欄位如下:

daemonize yes #後臺啟動
port 7000 #修改埠號,從7000到7005
cluster-enabled yes #開啟cluster,去掉註釋
cluster-config-file nodes-7000.conf
cluster-node-timeout 15000
appendonly yes
pidfile /var/run/redis_7000.pid

    相同操作處理其他五個文件夾,配置文件redis.conf中,將7000替換為對應的值。比如:7001文件下替換為7001。處理完成後,一次運行定義的每個文件夾下麵的redis,查看是否啟動成功。

    

 步驟4:安裝Ruby環境

    安裝Ruby環境。網上很多博客都是採用yum模式安裝的,但考慮到FQ等限制條件,本文采用離線模式安裝。

Ruby簡介

    Ruby是一種純粹的面向對象編程語言。它由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)創建於1993年。可以在 www.ruby-lang.org 的 Ruby 郵件列表上找到松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)的名字。在 Ruby 社區,松本也被稱為馬茨(Matz)。Ruby 是"程式員的最佳朋友"。Ruby 的特性與 Smalltalk、Perl 和 Python 類似。Perl、Python 和 Smalltalk 是腳本語言。Smalltalk 是一個真正的面向對象語言。Ruby,與 Smalltalk 一樣,是一個完美的面向對象語言。使用 Ruby 的語法比使用 Smalltalk 的語法要容易得多。

Ruby離線安裝

  1. Ruby下載地址:http://www.ruby-lang.org/en/downloads/  ,最新的版本為2.5.0。
  2. Ruby安裝參考網址:Linux 安裝Ruby詳解(線上和離線安裝)
  3. 在安裝之前,請確保使用賬號具有Root許可權,將下載的Ruby安裝包上傳到伺服器當中,通過xtfp5工具進行文件上傳:解壓上傳文件, tar -zxvf ruby-2.5.0.tar.gz,進入到ruby-2.5.0目錄執行指令make && make install安裝,安裝成功可通過指令:ruby -v查看版本號:

       

步驟5:安裝RubyGems環境

    安裝RubyGems環境。網上很多博客都是採用yum模式安裝的,但考慮到FQ等限制條件,本文采用離線模式安裝。

RubyGems簡介

    RubyGems 是 Ruby 的一個包管理器,它提供一個分發 Ruby 程式和庫的標準格式,還提供一個管理程式包安裝的工具。RubyGems 旨在方便地管理 gem 安裝的工具,以及用於分發 gem 的伺服器。這類似於 Ubuntu 下的apt-get, Centos 的 yum,Python 的 pip。RubyGems大約創建於2003年11月,從Ruby 1.9版起成為Ruby標準庫的一部分。

離線安裝RubyGems

如果你的 Ruby 低於 1.9 版本,也可以通過手動安裝:

  1. RubyGems下載地址:https://rubygems.org/pages/download
  2. RubyGems安裝參考網址:Linux 離線安裝Rubygems詳解
  3. 解壓下載文件併進入目錄,解壓指令tar -zxvf rubygems-2.7.4.tgz,執行命令:ruby setup.rb

       

步驟6:安裝openssl

    使用gem install 安裝 ruby redis。直接操作會報如下錯誤,查看原因是因為缺少openssl。

    

離線安裝openssl

  1. openssl下載地址:http://www.openssl.org/source/
  2. openssl安裝參考網址:配置群集時# gem install redis 報錯:Unable to require openssl, install OpenSSL and rebuild ruby
  3. 解壓下載文件併進入目錄,解壓指令如: tar -xzvf openssl-1.0.2n.tar.gz  ,執行以下命令:
tar -xzvf openssl-1.0.2n.tar.gz  
cd openssl-1.0.2n 
./config -fPIC --prefix=/usr/local/openssl enable-shared  
./config -t  make && make install
  1. 執行以上命令安裝openssl,安裝後查看版本號如下:

     

  1. 解決ssl.h文件找不到的問題,配置ruby文件,# ruby extconf.rb --with-openssl-include=/usr/local/openssl/include/ --with-openssl-lib=/usr/local/openssl/lib 
  2. 設置軟鏈接:ln -s /usr/local/src/ruby-2.2.3/include /  
  3. 再次編譯安裝,成功後如下圖所示:

    

步驟7:  安裝redis-trib.rb運行依賴的ruby的包redis-3.2.2.gem

  1. redis-3.2.2.gem下載地址:https://rubygems.global.ssl.fastly.net/gems/redis-3.2.2.gem
  2. 下載完成後上傳到伺服器上面,執行安裝命令如:gem install /usr/software/redis-3.2.2.gem   

      

步驟8:  使用redis-trib.rb創建集群

    使用create命令 --replicas 1 參數表示為每個主節點創建一個從節點,其他參數是實例的地址集合。可利用命令:./redis-trib.rb help查看使用介紹。運行集群創建shell腳本,cluster就創建成功了。最終的結果是後面的192.168.210.128:7000~192.168.210.128:7005中,會有3個會指定成master,而其它3個會指定成slave。

    註:利用redis-trib創建cluster的操作,只需要一次即可,假設系統關機,把所有6個節點全關閉後,下次重啟後,即自動進入cluster模式,不用再次redis-trib.rb create。

    

     查看redis進程啟動狀態,並開放防火牆中的對應埠。

    

    查看節點分配指令為:./redis-trib.rb check 192.168.210.128:7002  (任意一個集群的ip地址)

    

3.redis-cluster集群節點選舉,擴容與刪除

集群選舉

    現在模擬將7002節點掛掉,按照redis-cluster原理會選舉將 7002的從節點7005選舉為主節點。直接關閉7002的進程,在重新check可發現7005已經被自動選舉為主節點。當啟動7002後,7002將作為7005的從節點。

新增主節點

   新增一個節點D,redis cluster的這種做法是從各個節點的前面各拿取一部分slot到新增點上,也可設置從指定部分節點獲取。舉例如:在A,B,C節點上新增節點D。

  • 節點A覆蓋1365-5460
  • 節點B覆蓋6827-10922
  • 節點C覆蓋12288-16383
  • 節點D覆蓋0-1364,5461-6826,10923-12287

    新增一個節點7006作為主節點,操作步驟如下:

  1. 修改配置文件,新建一個對應的文件7006,並把複製配置文件redis.conf放入到文件7006下麵,並修改配置文件,把埠修改為7006,其他配置信息也參考前面的案例對應修改。節點配置信息成功後,啟動7006下麵的redis。
  2. 將7006加入到現有的集群中,輸入指令:./redis-trib.rb add-node 192.168.210.128:7006 192.168.210.128:7002。指令說明:dd-node是加入集群節點,192.168.210.128:7006為要加入的節點,192.168.210.128:7002 表示加入的集群的一個節點,用來辨識是哪個集群,理論上那個集群的節點都可以。
  3. 目前cluster已經定義7006為主節點,但是Cluster並未給7006分配哈希卡槽(0 slots)。
  4. redis-cluster在新增節點時並未分配卡槽,需要操作者手動對集群進行重新分片遷移數據,需要重新分片命令:reshard。操作如:redis-trib.rb reshard 192.168.210.128:7002。指令說明:這個命令是用來遷移slot節點的,後面的192.168.210.128:7002是表示是哪個集群,埠填[7000-7006]都可以,執行後:它提示需要遷移多少slot到7006上平分16384個哈希槽給4個節點:16384/4 = 4096,可移動4096個槽點到7006上。填寫7006的id:如ee3efb90e5ac0725f15238a64fc60a18a71205d7。

    

  1. redis-trib 會向你詢問重新分片的源節點(source node),即,要從特定的哪個節點中取出 4096 個哈希槽,還是從全部節點提取4096個哈希槽, 並將這些槽移動到7006節點上。如果不打算從特定的節點上取出指定數量的哈希槽,那麼可以向redis-trib輸入 all,這樣的話, 集群中的所有主節點都會成為源節點,redis-trib從各個源節點中各取出一部分哈希槽,湊夠4096個,然後移動到7006節點上。操作命令為:Source node #1:all  。

    

  1. 確認之後,redis-trib就開始執行分片操作,將哈希槽一個一個從源主節點移動到7006目標主節點。重新分片結束後可以check以下節點的分配情況。指令為:./redis-trib.rb check 192.168.210.128:7002。可查看擴容主節點是否成功。

新增從節點

  1.  新增一個節點7007作為從節點修改配置文件,新建一個對應的文件7007,並把複製配置文件redis.conf放入到文件7007下麵,並修改配置文件,把埠修改為7007,其他配置信息也參考前面的案例對應修改。節點配置信息成功後,啟動7007下麵的redis並加入到現有集群中。
  2. redis-trib增加從節點的命令為:./redis-trib.rb add-node --slave --master-id $[nodeid] 192.168.210.128:7007 192.168.210.128:7000 。操作指令含義:nodeid為要加到master主節點的node id,192.168.210.128:7007為新增的從節點,192.168.210.128:7000為集群的一個節點(集群的任意節點都行),用來辨識是哪個集群;如果沒有給定那個主節點--master-id的話,redis-trib將會將新增的從節點隨機到從節點較少的主節點上。
  3. 從節點不存在分片操作,與主節點對應的片一致。

移除主節點

  1. 移除節點使用redis-trib的del-node命令,redis-trib del-node 192.168.210.128:7002  ${node-id}  。操作指令含義: 192.168.210.128:7000為指定集群,node-id為要刪除的主節點。 和添加節點不同,移除節點node-id是必需的。

  2. 測試刪除7001主節點,redis cluster提示7001已經有數據了,不能夠被刪除,需要將他的數據轉移出去,也就是和新增主節點一樣需重新分片。

  3. 分區指令: ./redis-trib.rb reshard 192.168.210.128:7002  
  4. 輸入提示的需要移動的分片大小,分配給7001的slots為4096,輸入需要移動的片為4096。
  5. 輸入這些移除的slots如何分配給其他node,可指定一個具體node的id或者選擇所有。
  6. 最後確認後,開始移除節點。

    

移除從節點

  1. 移除節點使用redis-trib的del-node命令,redis-trib del-node 192.168.210.128:7002  ${node-id}  。操作指令含義: 192.168.210.128:7000為指定集群,node-id為要刪除的節點。 和添加節點不同,移除節點node-id是必需的。
  2. 從節點不存在分片問題,直接執行命令,確認移除即可。

4.redis-cluster集群與分散式連接池區別

    ShardedJedisPool是redis沒有集群功能之前客戶端實現的一個數據分散式方案,redis3.0提供集群之後,客戶端則採用JedisCluster實現連接redis集群環境。 ShardedJedisPool使用的是JedisShardInfo的instance的順序或者name來做的一致性哈希,JedisCluster使用的是CRC16演算法來做的哈希槽。 

    集群環境各個服務之間的數據是隔離的。無論是ShardedJedisPool的一致性哈希演算法還是JedisCluster的CRC16哈希槽演算法,都是把所有的服務疊加然後進行均勻的分割,分割出來的每一個段或槽都是不重覆的,所以導致存儲的數據彼此之間也是處於隔離狀態的。  

    jediscluster通過在客戶端調用捕捉異常,可實現集群環境下的高可用。Jedis還提供了對jedis sentinel pool的封裝,所以ShardedJedisPool發生主從切換的時候,web server都不需要重新配置和deploy。高可用性的極佳體現啊。

5.java客戶端調用redis-cluster

    更新pom文件中redis-clients的版本,低版本會報錯。<redis-clients.version>2.9.0</redis-clients.version>

    java客戶端調用redis-cluster可通過在java代碼中直接填寫地址或通過spring配置文件填寫,具體可參考上傳的代碼。在java中調用集群案例代碼如下:

/**
 * Description:  redis cluster 測試
 * Copyright:  2018 CSNT. All rights reserved.
 * Company:CSNT
 *
 * @author wangling
 * @version 1.0
 */
public class RedisClusterTestDemo {
            @Test
           public void testRedisCluster() throws Exception {
                JedisPoolConfig poolConfig = new JedisPoolConfig();
                Set<HostAndPort> nodes = new HashSet<HostAndPort>();
                HostAndPort hostAndPort = new HostAndPort("192.168.210.128", 7000);
                HostAndPort hostAndPort1 = new HostAndPort("192.168.210.128", 7001);
                HostAndPort hostAndPort2 = new HostAndPort("192.168.210.128", 7002);
                HostAndPort hostAndPort3 = new HostAndPort("192.168.210.128", 7003);
                HostAndPort hostAndPort4 = new HostAndPort("192.168.210.128", 7004);
                HostAndPort hostAndPort5 = new HostAndPort("192.168.210.128", 7005);
                nodes.add(hostAndPort);
                nodes.add(hostAndPort1);
                nodes.add(hostAndPort2);
                nodes.add(hostAndPort3);
                nodes.add(hostAndPort4);
                nodes.add(hostAndPort5);
                JedisCluster jedisCluster = new JedisCluster(nodes,5000,1000);
                jedisCluster.set("jedisKey","wangling test jedisKey");
                    //redis內部會創建連接池,從連接池中獲取連接使用,然後再把連接返回給連接池
                String string = jedisCluster.get("jedisKey");
                System.out.println(string);
                 }
         }

//基於配置文件調用,完整配置信息參考上傳的源代碼
/**
 * Description:  redis cluster 測試
 * Copyright:  2018 CSNT. All rights reserved.
 * Company:CSNT
 *
 * @author wangling
 * @version 1.0
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:redis-cluster-context.xml")
public class JedeisClusterTest {
     @Autowired
     private JedisCluster jedisCluster;

     @Test
     public void testJedisCluster(){
          jedisCluster.set("jedisCluster", "wangling test jedisCluster");
          String val = jedisCluster.get("jedisCluster");
          System.out.println(val);
     }
}

    軟體運行截圖如下:

6.參考網址

7.源碼下載

在Git上面下載:https://github.com/wuya11/redisClusterDemo


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • UDF函數中定義的集合對象何時初始化 udf函數放在sql中對某個欄位進行處理,那麼在底層會創建一個該類的對象,這個對象不斷的去調用這個evaluate(...)方法,截圖如下: 1.1 如果說對於每一條傳入UDF中需要處理的數據都需要全新的集合對象,那麼這個時候集合對象就需要在類中聲明,在eval ...
  • 聯合索引概念:當系統中某幾個欄位經常要做查詢,並且數據量較大,達到百萬級別,可多個欄位建成索引 使用規則: 1.最 左 原則,根據索引欄位,由左往右依次and(where欄位很重要,從左往右) 2.Or 不會使用聯合索引 3.where語句中查詢欄位包含全部索引欄位,欄位順序無關,可隨意先後... ...
  • 以下為二維表信息 //統計嚴重等級Bug SELECT severity,count(severity) FROM `bf_bugview` where product_id=476 GROUP BY severity //統計創建者Bug SELECT created_by_name,count( ...
  • 近日在研究v$latch視圖時,發現一個從未見過的數據類型。v$latch 中ADDR屬性的數據類型為RAW(4|8) 同時也發現v$process中的ADDR屬性的數據類型也為RAW(4|8)。於是查了一下oracle 的SQL Language Reference文檔,文檔如下描述: The R ...
  • 接觸變成時間不久,之前對於MySQL的瞭解局限於簡單的CURD,沒有系統和深入的學習過,最近想要更深入的學習和瞭解一下MySQL,打算先從官方文檔入手。 最新官方文檔:https://dev.mysql.com/doc/refman/8.0/en 1. MySQL對標準SQL的擴展 (1) MySQ ...
  • 前段時間因工作需求,特地學習了下sp_send_dbmail的使用,發現網上的示例對我這樣的菜鳥太不友好/(ㄒoㄒ)/~~,好不容易完工來和大家分享一下,不談理論,只管實踐! 如下是實際需求: -- Title: 集團資質一覽表-- Description1:<1、距離到期日期1年內和已過期的發到期 ...
  • [20180124]奇怪的SQL*Net message from dblink.txt--//生產系統出現大量的SQL*Net message from dblink事件,自己分析看看.1.環境:--//這個環境是伺服器在分院,有時候要通過dblink訪問總院的資料庫.xxxx> @ ver1PO ...
  • 中途產生報錯:已連接到空閑常式、ora-03113:通信通道的文件結尾、no login、ora-12514:TNS:監聽程式當前無法識別連接描述符中請求的服務、ora-24324:未初始化服務句柄、ora-03114:未連接到ORACLE、ora-01034:ORACLE not availabl... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...