天天看點

redis主從複制以及哨兵機制

7 Redis的主從複制

7.1 什麼是主從複制

持久化保證了即使redis服務重新開機也不會丢失資料,因為redis服務重新開機後會将硬碟上持久化的資料恢複到記憶體中,但是當redis伺服器的硬碟損壞了可能會導緻資料丢失,如果通過redis的主從複制機制就可以避免這種單點故障,如下圖:
           
redis主從複制以及哨兵機制

說明:

  • 主redis中的資料有兩個副本(replication)即從redis1和從redis2,即使一台redis伺服器當機其它兩台redis服務也可以繼續提供服務。
  • 主redis中的資料和從redis上的資料保持實時同步,當主redis寫入資料時通過主從複制機制會複制到兩個從redis服務上。
  • 隻有一個主redis,可以有多個從redis。
  • 主從複制不會阻塞master,在同步資料時,master 可以繼續處理client 請求
  • 一個redis可以即是主又是從,如下圖:
    redis主從複制以及哨兵機制

7.2 主從配置

7.2.1 主redis配置

無需特殊配置。

7.2.2 從redis配置

方式一:修改從redis伺服器上的redis.conf檔案

# slaveof <masterip> <masterport>
slaveof 127.0.0.1 6379
           

上邊的配置說明目前該【從redis伺服器】所對應的【主redis伺服器】的IP是192.168.101.3,端口是6379

方式2:動态設定

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

slaveof 192.168.33.130 6379

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

主從複制過程

redis主從複制以及哨兵機制

過程:

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

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

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

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

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

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

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主從複制以及哨兵機制

主觀下線和客觀下線:

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

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

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

從節點:主觀下線狀态

sentinel配置

修改sentinel.conf檔案

[python] view plain copy
sentinel monitor mymaster        #最後一個參數視情況決定  
           
redis主從複制以及哨兵機制

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

啟動sentinel

[python] view plain copy
redis-sentinel sentinel.conf
           

啟動後結果圖示:

redis主從複制以及哨兵機制

sentinel日志明細說明

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

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

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

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

sentinel的一些指令

[python] view plain copy
INFO  
           

sentinel的基本狀态資訊

[python] view plain copy
SENTINEL masters  
           

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

[python] view plain copy
SENTINEL slaves <master name>  
           

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

[python] view plain copy
SENTINEL get-master-addr-by-name <master name>  
           

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

[python] view plain copy
SENTINEL reset <pattern>  
           

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

[python] view plain copy
SENTINEL failover <master name>  
           

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

java操作sentinel

代碼示例:

[java] view plain copy
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();  
        // 控制一個pool最多有多少個jedis執行個體。  
        poolConfig.setMaxTotal();  
        // 表示當borrow(引入)一個jedis執行個體時,最大的等待時間,如果超過等待時間,則直接抛出JedisConnectionException;  
        poolConfig.setMaxWaitMillis();  
        // 在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();  
    }  
}  
列印結果:
           

參考文章:http://blog.csdn.net/u011204847/article/details/51307044

繼續閱讀