面試準備之redis三種集羣模式

目錄

主從模式

主從模式的好處

主從模式的缺點

主從節點數據同步的原理

哨兵模式

哨兵模式的優點

哨兵模式的缺點

哨兵模式的原理

集羣模式

集羣模式的優點

集羣模式的原理


現在開始寫redis系列,雖然都是照着別人的博客在寫,但是我儘量翻譯成我自己的理解,平時項目中有用redis,但是對reids的關注比較少,所以自認爲redis是自己比較薄弱的一環。其實在一年之前爲了找工作,reids這塊還是準備了一些的,但是感覺沒有形成系統,所以從今天開始將redis的知識都梳理一遍。

今天寫的這redis集羣在面試的時候有兩家公司被問到過,一家是中國平安,當時問redis 哨兵模式,自己一臉懵逼,後面再到松鼠拼拼去面試也被問到了,當時剛好自己看了,我覺得自己的回答令面試官挺滿意的。不過最後都沒有過,哈哈。

redis集羣有三種方式:主從模式,哨兵模式,redis-cluster集羣(我叫做多主結點模式)

主從模式

即一個主節點多個從結點,能夠實現主從數據同步。

主從模式的好處

1.實現數據備份。

2.實現讀寫分離,減輕主結點讀操作的壓力。

主從模式的缺點

1.當主節點掛掉後,整個服務變得不可用,系統不能自動恢復。

2.每一個節點存儲的值都是一樣的,當達到存儲上限後,很難在線擴容。

主從節點數據同步的原理

1.從節點連接上了主節點後,會發送一個fsync的命令,主節點收到fsync命令後會執行bgsave命令,將內存的數據生成一個RDB文件,並開闢一個緩存空間,用來緩存後面過來的寫操作。

2.主節點將生成的RDB文件發送給從節點,發送完成後,再將緩存區裏面的寫操作發送給從節點。

3.從節點接受到主節點的RDB文件,丟棄以前舊的數據,載入RDB文件。載入完RDB文件後,開啓接受來自緩存區的寫命令。

4.後面主服務器每接受一個寫命令後,會發送給從服務器,從服務器會執行相同的操作

哨兵模式

哨兵模式是在加了主從節點基礎之上,新增了哨兵結點,這些哨兵結點能將監控主從結點的狀態,並能實現故障轉移,當主節點掛掉之後,能選中一個從節點作爲新的主節點,這樣服務能接着正常運行。

哨兵模式的優點

1.實現數據備份和讀寫分離操作。

2.能監控主從結點的狀態,並能通過api通知其他程序。

3.當主結點掛掉後,哨兵結點能選舉出一個從節點作爲新的主結點,這樣程序還能接着運行。

哨兵模式的缺點

哨兵模式雖然解決了故障轉移,但是卻沒有解決系統動態擴容的問題,由於每一個結點存儲的內容都一樣,會出現空間大小的瓶頸。

哨兵模式的原理

先說一下PING命令和INFO命令的區別

PING命令是哨兵節點用來監控主從節點狀態的,監控主從節點有沒有下線。

INFO命令是哨兵節點用來獲取主從節點信息,發現新的從節點,根據獲取到的主節點信息來進行角色變更,這也是爲什麼哨兵節點只需要連接主節點就能發現其他從節點的原因。

1.哨兵結點會以每秒的速度向主節點,從節點和哨兵節點發送PING命令。當在規定的時間內還沒有收到應答的時候,這個節點會被標記爲主觀下線。

2.如果被標記的主觀下線的節點是主節點的話,其他哨兵節點會以每秒一次的頻率(發送INFO命令)確認這個主節點是否主觀下線,如果有足夠多的哨兵節點(數量可以在配置文件裏面配置)確認這個主節點主觀下線了,那這個主節點就會被標註成客觀下線。

3.當主節點被標註成客觀下線後,哨兵節點會選舉出一個從節點作爲新的主節點。而選舉的依據是:
A.先判斷每個節點的優先級,選出優先級最高的從節點作爲主節點。
B.如果大家優先級都一樣高,選出從節點中複製偏移量最大的作爲主節點。
C.如果大家複製偏移量一樣大,選出id最小的從節點作爲主節點。

集羣模式

集羣模式的優點

1.故障自動轉移。

2.能夠實現自動擴容,有多個主節點,每一個主節點存儲的值都不一樣,能在線添加主節點和刪除節點。

集羣模式的原理

集羣模式擁有多個主節點,每一個節點都有獨立的讀寫能力,主節點直接相互通信,每一個主節點下面可以掛多個從節點。redis集羣將劃分了16384個哈希槽,所有的數據在存入到redis的時候只需對它的key進行CRC16計算,然後對16384進行取模運算,這樣就可以確認這個值會被存入到哪一個哈希槽中。

並且每一個主節點都會有一個數據分佈表,這個數據分佈表裏面會存儲的有哈希槽和節點之間的映射關係,連接一個主節點,當向redis存儲值的時候,如果這個值對應的哈希槽剛好落在了這個主節點上,那麼直接執行命令後返回結果,如果這個值對應的哈希槽不在這個主節點上,那麼主節點會返回一個MOVE錯誤,並且會帶上這個值應該存放的主節點信息,這樣客戶端可以找連接正確的主節點進行操作,但是這樣有一個壞處就是會進行兩次訪問。還有一種做法是客戶端獲取到整個的集羣分佈表,這樣每次請求就能正確的找到節點。如果當根據數據分佈表來查找對應的哈希槽出現錯誤,那麼可以執行cluster nodes命令更新數據分佈表。

當有一個節點的主從節點變得都不可用的時候,這個集羣也會變得不可用,如果有一半以上的主節點宕機了,那這個集羣也會變得不可用。

節點A會定期ping消息給節點B,如果節點B能接受消息,就會返回一個pong消息給節點A,節點A就會更新和B節點通信的最新時間
當在規定的時間內節點A還沒有收到節點B給的返回時間後,節點A會將節點B標記爲主觀下線,當超過一半的主節點認爲這個節點主觀下線的時候,那這個節點會被標記爲客觀下線,然後從這個主節點下面的從節點選舉出一個作爲新的主節點。

開啓redis集羣模式的關鍵是要修改配置文件裏面的:

cluster-enabled yes   #開啓集羣模式
package com.pc.jedis.test;
 
import java.util.HashSet;
import java.util.Set;
 
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
 
/**
 * Jedis集羣測試
 * 
 * @author Switch
 * @data 2017年2月11日
 * @version V1.0
 */
public class JedisClusterTest {
    public static void main(String[] args) {
        // 創建並填充節點信息
        Set<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("192.168.37.131", 7001));
        nodes.add(new HostAndPort("192.168.37.131", 7002));
        nodes.add(new HostAndPort("192.168.37.131", 7003));
        nodes.add(new HostAndPort("192.168.37.131", 7004));
        nodes.add(new HostAndPort("192.168.37.131", 7005));
        nodes.add(new HostAndPort("192.168.37.131", 7006));
 
        // 創建JedisCluster對象
        JedisCluster jedisCluster = new JedisCluster(nodes);
 
        // 使用jedisCluster操作redis
        String key = "jedisCluster";
        String setResult = jedisCluster.set(key, "hello redis!");
        System.out.println(setResult);
 
        String getResult = jedisCluster.get(key);
        System.out.println(getResult);
 
        // 關閉jedisCluster(程序執行完後才能關閉,內部封裝了連接池)
        jedisCluster.close();
    }
}

 

 

  

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章