天天看點

Redis主從複制和叢集配置Redis主從複制和叢集配置

Redis主從複制和叢集配置

redis主從複制

概述

1、redis的複制功能是支援多個資料庫之間的資料同步。一類是主資料庫(master)一類是從資料庫(slave),主資料庫可以進行讀寫操作,當發生寫操作的時候自動将資料同步到從資料庫,而從資料庫一般是隻讀的,并接收主資料庫同步過來的資料,一個主資料庫可以有多個從資料庫,而一個從資料庫隻能有一個主資料庫。

2、通過redis的複制功能可以很好的實作資料庫的讀寫分離,提高伺服器的負載能力。主資料庫主要進行寫操作,而從資料庫負責讀操作。

主從複制過程

主從複制過程:見下圖

Redis主從複制和叢集配置Redis主從複制和叢集配置

過程:

1:當一個從資料庫啟動時,會向主資料庫發送sync指令,

2:主資料庫接收到sync指令後會開始在背景儲存快照(執行rdb操作),并将儲存期間接收到的指令緩存起來

3:當快照完成後,redis會将快照檔案和所有緩存的指令發送給從資料庫。

4:從資料庫收到後,會載入快照檔案并執行收到的緩存的指令。

注意:redis2.8之前的版本:當主從資料庫同步的時候從資料庫因為網絡原因斷開重連後會重新執行上述操作,不支援斷點續傳。

redis2.8之後支援斷點續傳。

配置

Redis主從結構支援一主多從

主節點:192.168.33.130

從節點:192.168.33.131

注意:所有從節點的配置都一樣

方式1:手動修改配置檔案

隻需要額外修改從節點中redis的配置檔案中的slaveof屬性即可

slaveof 192.168.33.130 6379
           

配置修改圖示:

Redis主從複制和叢集配置Redis主從複制和叢集配置

配置效果圖示:

1、192.168.33.130主機:啟動130主節點上面的redis,檢視redis的info資訊

Redis主從複制和叢集配置Redis主從複制和叢集配置

2、192.168.33.131主機:啟動131從節點上面的redis,檢視redis的info資訊

Redis主從複制和叢集配置Redis主從複制和叢集配置

方式2:動态設定

通過redis-cli 連接配接到從節點伺服器,執行下面指令即可。

slaveof 192.168.33.130 6379

示範結果和手動方式一緻。

注意事項

如果你使用主從複制,那麼要確定你的master激活了持久化,或者確定它不會在當掉後自動重新開機。原因:

slave是master的完整備份,是以如果master通過一個空資料集重新開機,slave也會被清掉。

在配置redis複制功能的時候如果主資料庫設定了密碼,需要在從資料的配置檔案中通過masterauth參數設定主資料庫的密碼,這樣從資料庫在連接配接主資料庫時就會自動使用auth指令認證了。相當于做了一個免密碼登入。

redis的Sentinel

sentinel功能

redis的sentinel系統用于管理多個redis伺服器,該系統主要執行三個任務:監控、提醒、自動故障轉移。

1、監控(Monitoring): Redis Sentinel實時監控主伺服器和從伺服器運作狀态,并且實作自動切換。

2、提醒(Notification):當被監控的某個 Redis 伺服器出現問題時, Redis Sentinel 可以向系統管理者發送通知, 也可以通過 API 向其他程式發送通知。

3、自動故障轉移(Automatic failover): 當一個主伺服器不能正常工作時,Redis Sentinel 可以将一個從伺服器更新為主伺服器, 并對其他從伺服器進行配置,讓它們使用新的主伺服器。當應用程式連接配接Redis 伺服器時, Redis Sentinel會告之新的主伺服器位址和端口。

注意:在使用sentinel監控主從節點的時候,從節點需要是使用動态方式配置的,如果直接修改配置檔案,後期sentinel實作故障轉移的時候會出問題。

圖示sentinel

Redis主從複制和叢集配置Redis主從複制和叢集配置

主觀下線和客觀下線:

1、主觀下線狀态:當一個sentinel認為一個redis服務連接配接不上的時候,會給這個服務打個标記為下線狀态。

2、客觀下線狀态:當多個sentinel認為一個redids連接配接不上的時候,則認為這個redis服務确實下線了。這裡的多個sentinel的個數可以在配置檔案中設定。

主節點:主觀下線和客觀下線

從節點:主觀下線狀态

sentinel配置

修改sentinel.conf檔案

sentinel monitor mymaster 192.168.33.130 6379 2     #最後一個參數視情況決定
           
Redis主從複制和叢集配置Redis主從複制和叢集配置

最後一個參數為需要判定客觀下線所需的主觀下線sentinel個數,這個參數不可以大于sentinel個數。

啟動sentinel

redis-sentinel sentinel.conf
           

啟動後結果圖示:

Redis主從複制和叢集配置Redis主從複制和叢集配置

sentinel日志明細說明

http://redisdoc.com/topic/sentinel.html

通過訂閱指定的頻道資訊,當伺服器出現故障得時候通知管理者

用戶端可以将 Sentinel 看作是一個隻提供了訂閱功能的 Redis 伺服器,你不可以使用 PUBLISH 指令向這個伺服器發送資訊,但你可以用 SUBSCRIBE 指令或者 PSUBSCRIBE 指令, 通過訂閱給定的頻道來擷取相應的事件提醒。

一個頻道能夠接收和這個頻道的名字相同的事件。 比如說, 名為 +sdown 的頻道就可以接收所有執行個體進入主觀下線(SDOWN)狀态的事件。

sentinel的一些指令

INFO
           

sentinel的基本狀态資訊

SENTINEL masters
           

列出所有被監視的主伺服器,以及這些主伺服器的目前狀态

SENTINEL slaves <master name>
           

列出給定主伺服器的所有從伺服器,以及這些從伺服器的目前狀态

SENTINEL get-master-addr-by-name <master name>
           

傳回給定名字的主伺服器的 IP 位址和端口号

SENTINEL reset <pattern>
           

重置所有名字和給定模式 pattern 相比對的主伺服器。重置操作清除主伺服器目前的所有狀态, 包括正在執行中的故障轉移, 并移除目前已經發現和關聯的, 主伺服器的所有從伺服器和 Sentinel 。

SENTINEL failover <master name>
           

當主伺服器失效時, 在不詢問其他 Sentinel 意見的情況下, 強制開始一次自動故障遷移,但是它會給其他sentinel發送一個最新的配置,其他sentinel會根據這個配置進行更新

java操作sentinel

代碼示例:

import java.util.HashSet;
//需要在pom.xml檔案中引入jedis依賴
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

public class SentinelTest {

    public static void main(String[] args) {
        // 使用HashSet添加多個sentinel
        HashSet<String> sentinels = new HashSet<String>();
        // 添加sentinel主機和端口
        sentinels.add("192.168.33.131:26379");

        // 建立config
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        // 控制一個pool最多有多少個狀态為idle(空閑的)的jedis執行個體。
        poolConfig.setMaxIdle(10);
        // 控制一個pool最多有多少個jedis執行個體。
        poolConfig.setMaxTotal(100);
        // 表示當borrow(引入)一個jedis執行個體時,最大的等待時間,如果超過等待時間,則直接抛出JedisConnectionException;
        poolConfig.setMaxWaitMillis(2000);
        // 在borrow一個jedis執行個體時,是否提前進行validate操作;如果為true,則得到的jedis執行個體均是可用的;
        poolConfig.setTestOnBorrow(true);

        // 通過Jedis連接配接池建立一個Sentinel連接配接池
        JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,poolConfig);
        // 擷取master的主機和端口
        HostAndPort currentHostMaster = pool.getCurrentHostMaster();
        System.out.println(currentHostMaster.getHost() + "--"+ currentHostMaster.getPort());
        // 從Sentinel池中擷取資源
        Jedis resource = pool.getResource();
        // 列印資源中key為name的值
        System.out.println(resource.get("name"));
        // 關閉資源
        resource.close();
    }
}
           

列印結果:

Redis主從複制和叢集配置Redis主從複制和叢集配置

redis叢集

簡介

redis叢集是一個無中心的分布式Redis存儲架構,可以在多個節點之間進行資料共享,解決了Redis高可用、可擴充等問題。redis叢集提供了以下兩個好處

1、将資料自動切分(split)到多個節點

2、當叢集中的某一個節點故障時,redis還可以繼續處理用戶端的請求。

一個 Redis 叢集包含 16384 個哈希槽(hash slot),資料庫中的每個資料都屬于這16384個哈希槽中的一個。叢集使用公式 CRC16(key) % 16384 來計算鍵 key 屬于哪個槽。叢集中的每一個節點負責處理一部分哈希槽。

叢集中的主從複制

叢集中的每個節點都有1個至N個複制品,其中一個為主節點,其餘的為從節點,如果主節點下線了,叢集就會把這個主節點的一個從節點設定為新的主節點,繼續工作。這樣叢集就不會因為一個主節點的下線而無法正常工作。

注意:

1、如果某一個主節點和他所有的從節點都下線的話,redis叢集就會停止工作了。redis叢集不保證資料的強一緻性,在特定的情況下,redis叢集會丢失已經被執行過的寫指令

2、使用異步複制(asynchronous replication)是 Redis 叢集可能會丢失寫指令的其中一個原因,有時候由于網絡原因,如果網絡斷開時間太長,redis叢集就會啟用新的主節點,之前發給主節點的資料就會丢失。

Redis主從複制和叢集配置Redis主從複制和叢集配置

安裝配置

修改配置檔案redis.conf

daemonize yes
port 6379
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
           

要讓叢集正常運作至少需要三個主節點

我們這裡就簡單在一台主機上建立6個redis節點來示範叢集配置,實際生産環境中需要每個節點一台主機。

我們要建立的6個redis節點,其中三個為主節點,三個為從節點,對應的redis節點的ip和端口對應關系如下:

192.168.33.130:7000
192.168.33.130:7001
192.168.33.130:7002
192.168.33.130:7003
192.168.33.130:7004
192.168.33.130:7005
           

1、首先我們建立6個以端口為名稱的檔案夾(由于每個redis節點啟動的時候,都會在目前檔案夾下建立快照檔案,是以我們需要建立每個節點的啟動目錄)

mkdir 7000
mkdir 7001
mkdir 7002
mkdir 7003
mkdir 7004
mkdir 7005
           

2、接下來把每個節點啟動所需要的配置檔案拷貝到相應的啟動目錄:

cp redis.conf  7000
cp redis.conf  7001
cp redis.conf  7002
cp redis.conf  7003
cp redis.conf  7004
cp redis.conf  7005
           

3、然後我們進入每個啟動目錄,修改之前拷貝的redis.conf檔案中的端口port 為上面列出的對應端口。

最終每個節點的配置類似于:

daemonize yes
port 6379     #隻有端口不同,其他相同
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
           

4、進入每個啟動目錄,以每個目錄下的redis.conf檔案啟動

Redis主從複制和叢集配置Redis主從複制和叢集配置

使用指令檢視redis節點是否啟動

ps -ef | grep redis
           
Redis主從複制和叢集配置Redis主從複制和叢集配置

5、建立叢集指令

redis-trib.rb  create --replicas 1 192.168.33.130:7000 192.168.33.130:7001 192.168.33.130:7002 192.168.33.130:7003 192.168.33.130:7004 192.168.33.130:7005
           

注意:

5.1、執行上面的指令的時候可能會報錯,因為是執行的ruby的腳本,需要ruby的環境

錯誤内容:

Redis主從複制和叢集配置Redis主從複制和叢集配置

是以我們需要安裝ruby的環境,這裡推薦使用yum安裝:

yum install ruby
           

5.2、安裝ruby後,執行指令可能還會報錯,提示缺少rubygems元件,使用yum安裝

Redis主從複制和叢集配置Redis主從複制和叢集配置

解決方法:

yum install rubygems
           

5.3、上面兩個步驟後,執行建立叢集目錄可能還會報錯,提示不能加載redis,是因為缺少redis和ruby的接口,使用gem 安裝。

Redis主從複制和叢集配置Redis主從複制和叢集配置

解決方法:

gem install redis
           

上面三個問題解決後,啟動建立叢集應該可以正常啟動了:

Redis主從複制和叢集配置Redis主從複制和叢集配置
Redis主從複制和叢集配置Redis主從複制和叢集配置

這裡輸入yes

最後結果:

Redis主從複制和叢集配置Redis主從複制和叢集配置

到此,我們的叢集搭建成功了。

6、接下來我們使用指令進入叢集環境

redis-cli -c -p 7000
           

redis叢集操作

使用redis-cli用戶端來操作redis叢集,使用指令 :

redis-cli -c  -p [port]
           
Redis主從複制和叢集配置Redis主從複制和叢集配置

檢視叢集中的所有主節點資訊

redis-cli -c -p 7000 cluster nodes [| grep master]
           
Redis主從複制和叢集配置Redis主從複制和叢集配置

redis叢集添加節點

根據添加節點類型的不同,有兩種方法來添加新節點

1、主節點:如果添加的是主節點,那麼我們需要建立一個空節點,然後将某些哈希槽移動到這個空節點裡面

2、從節點:如果添加的是從節點,我們也需要建立一個空節點,然後把這個新節點設定成叢集中某個主節點的複制品。

 添加節點:

1、首先把需要添加的節點啟動

建立7006目錄,拷貝7000中的redis.conf到7006中,然後修改端口port為7006,修改好後進入7006目錄啟動這個節點:

redis-server redis.conf
           

2、執行以下指令,将這個新節點添加到叢集中:

redis-trib.rb add-node 192.168.33.130:7006 192.168.33.130:7000
           

結果圖示:

Redis主從複制和叢集配置Redis主從複制和叢集配置

3、執行指令檢視剛才新增的節點:

redis-cli -c -p 7000 cluster nodes
           
Redis主從複制和叢集配置Redis主從複制和叢集配置

4、增加了新的節點之後,這個新的節點可以成為主節點或者是從節點

4.1将這個新增節點變成從節點

前面我們已經把這個新節點添加到叢集中了,現在我們要讓新節點成為192.168.33.130:7001的從節點,隻需要執行下面的指令就可以了,指令後面的節點ID就是192.168.33.130:7001的節點ID。(注意,這個從節點哈希槽必須為空,如果不為空,則需要轉移掉哈希槽使之為空)

redis-cli -c -p 7006 cluster replicate a246963893faf03c45cc19ef4188f82f5393bfef
           
Redis主從複制和叢集配置Redis主從複制和叢集配置

使用下面指令來确認一下192.168.33.130:7006是否已經成為192.168.33.130:7001的從節點。

redis-cli -p 7000 cluster nodes | grep slave | grep a246963893faf03c45cc19ef4188f82f5393bfef
           
Redis主從複制和叢集配置Redis主從複制和叢集配置

4.2、将這個新增節點變成主節點:

使用redis-trib程式,将叢集中的某些哈希槽移動到新節點裡面,這個新節點就成為真正的主節點了。執行下面的指令對叢集中的哈希槽進行移動:

redis-trib.rb reshard 192.168.33.130:7000
           

指令執行後,系統會提示我們要移動多少哈希槽,這裡移動1000個

Redis主從複制和叢集配置Redis主從複制和叢集配置

然後還需要指定把這些哈希槽轉移到哪個節點上

Redis主從複制和叢集配置Redis主從複制和叢集配置

輸入我們剛才新增的節點的ID

d113e0f033c98e2f6b88fb93e6e98866256d85c4

然後需要我們指定轉移哪幾個幾點的哈希槽

Redis主從複制和叢集配置Redis主從複制和叢集配置

輸入all 表示從所有的主節點中随機轉移,湊夠1000個哈希槽

然後再輸入yes,redis叢集就開始配置設定哈希槽了。

Redis主從複制和叢集配置Redis主從複制和叢集配置

至此,一個新的主節點就添加完成了,執行指令檢視現在的叢集中節點的狀态

redis-cli -c -p 7000 cluster nodes
           

結果圖示:

Redis主從複制和叢集配置Redis主從複制和叢集配置

Redis叢集删除節點

1、如果删除的節點是主節點,這裡我們删除192.168.33.130:7006節點,這個節點有1000個哈希槽

首先要把節點中的哈希槽轉移到其他節點中,執行下面的指令:

redis-trib.rb reshard 192.168.33.130:7000
           

系統會提示我們要移動多少哈希槽,這裡移動1000個,因為192.168.33.130:7006節點有1000個哈希槽。

Redis主從複制和叢集配置Redis主從複制和叢集配置

然後系統提示我們輸入要接收這些哈希槽的節點的ID,這裡使用192.168.33.130:7001的節點ID

Redis主從複制和叢集配置Redis主從複制和叢集配置

然後要我們選擇從那些節點中轉出哈希槽,這裡一定要輸入192.168.33.130:7006這個節點的ID

Redis主從複制和叢集配置Redis主從複制和叢集配置

最後輸入done表示輸入完畢。

最後一步,使用下面的指令把這個節點删除

redis-trib.rb del-node 192.168.33.130:7000 d113e0f033c98e2f6b88fb93e6e98866256d85c4    //最後一個參數為需要删除的節點ID
           
Redis主從複制和叢集配置Redis主從複制和叢集配置

2、如果是從節點,直接删除即可。

redis-trib.rb del-node 192.168.33.130:7000 d113e0f033c98e2f6b88fb93e6e98866256d85c4   //最後一個參數為需要删除節點的ID
           
Redis主從複制和叢集配置Redis主從複制和叢集配置

java操作redis叢集

向Redis叢集中存入鍵值:

Redis主從複制和叢集配置Redis主從複制和叢集配置

代碼示例:

import java.util.HashSet;
//需要再pom.xml中引入jedis依賴
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisCluster {
    public static void main(String[] args) {
        //初始化集合,用于裝下面的多個主機和端口
        HashSet<HostAndPort> nodes = new HashSet<HostAndPort>();
        
        //建立多個主機和端口執行個體
        HostAndPort hostAndPort = new HostAndPort("192.168.33.130", 7000);
        HostAndPort hostAndPort1 = new HostAndPort("192.168.33.130", 7001);
        HostAndPort hostAndPort2 = new HostAndPort("192.168.33.130", 7002);
        HostAndPort hostAndPort3 = new HostAndPort("192.168.33.130", 7003);
        HostAndPort hostAndPort4 = new HostAndPort("192.168.33.130", 7004);
        HostAndPort hostAndPort5 = new HostAndPort("192.168.33.130", 7005);
        
        //添加多個主機和端口到集合中
        nodes.add(hostAndPort);
        nodes.add(hostAndPort1);
        nodes.add(hostAndPort2);
        nodes.add(hostAndPort3);
        nodes.add(hostAndPort4);
        nodes.add(hostAndPort5);
        
        //建立config
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        //通過config建立叢集執行個體
        JedisCluster jedisCluster = new JedisCluster(nodes,poolConfig);
        //擷取叢集中的key為name鍵的值
        String str = jedisCluster.get("name");
        System.out.println(str);
    }
}
           

列印結果:

Redis主從複制和叢集配置Redis主從複制和叢集配置