天天看點

redis叢集模式:redis單點、redis主從、redis哨兵sentinel,redis叢集cluster

目錄

redis單點、redis主從、redis哨兵 sentinel,redis叢集cluster配置搭建與使用

redis是如今被網際網路公司使用最廣泛的一個中間件,我們打開GitHub搜尋redis,邊可以看到,該項目的介紹是這樣的:

Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes, HyperLogLogs, Bitmaps.

從這句話中,我們可以提取其特性的關鍵字:

in-memory database ,記憶體資料庫

support:Strings , lists, sets ,hashes ,hyperloglogs, bitmaps

也就是高性能,支援資料類型多。本文假設你已經了解redis的基本使用,進而讨論redis的單點,高可用,叢集。

redis的安裝十分簡單,打開redis的官網 redis.io 。

下載下傳一個最新版本的安裝包,如 redis-version.tar.gz

解壓 tar zxvf redis-version.tar.gz

執行 make (執行此指令可能會報錯,例如确實gcc,一個個解決即可)

如果是 mac 電腦,安裝redis将十分簡單執行brew install redis即可。

安裝好redis之後,我們先不慌使用,先進行一些配置。打開redis.conf檔案,我們主要關注以下配置:

安裝好redis之後,我們來運作一下。啟動redis的指令為 :

redishome/bin/redis-server path/to/redis.config

假設我們沒有配置背景運作(即:daemonize no),那麼我們會看到如下啟動日志:

無論是否配置了背景運作,啟動成功之後,我們可以新開一個指令行視窗來操作試試。

使用指令:telnet localhost 6379 來連接配接redis,或者你可以直接使用代碼來連接配接測試。連接配接之後,看到如下資訊:

我們輸入幾個指令試試:

如此,我們便體驗了一把redis,可以說是非常簡單了。剛才我們是使用指令行來操作redis的,下面我們來使用代碼操作一下redis,以Java為例,我們使用一個開源的 java - redis用戶端。

打開GitHub,搜尋redis,進入到項目首頁之後,我們可以看到使用方法:

加入jedis依賴

redis.clients

   jedis

   3.0.0

   jar

   compile

編寫代碼如下

Jedis jedis = new Jedis("localhost",6379);

jedis.set("hello", "world");

String value = jedis.get("hello");

System.out.println(value); // get world

jedis.del("hello");

System.out.println(jedis.get("hello"));// get null

上面jedis操作redis的例子很簡單,除了使用jedis之外,還可以使用spring-redis。步驟如下

配置redis

編寫代碼

public class Example {

}

Lettuce是一個基于netty的 非阻塞的 redis用戶端。支援Java8以及響應式。其官網為 lettuce.io/。Lettuce也可以和spring搭配使用。

使用Lettuce需要加入如下maven依賴:

基本的 get,set示例代碼如下:

上面我們啟動了一台redis,并對其進行操作。當然這隻是實驗性的玩玩。假設我們生産環境使用了一台redis,redis挂了怎麼辦?如果等到運維重新開機redis,并恢複好資料,可能需要花費很長時間。那麼在這期間,我們的服務是不可用的,這應該是不能容忍的。假設我們做了主從,主庫挂了之後,運維讓從庫接管,那麼服務可以繼續運作,正所謂有備無患。

redis主從配置非常簡單,過程如下(ps 示範情況下主從配置在一台電腦上):

複制兩個redis配置檔案(啟動兩個redis,隻需要一份redis程式,兩個不同的redis配置檔案即可)

mkdir redis-master-slave

cp path/to/redis/conf/redis.conf path/to/redis-master-slave master.conf

cp path/to/redis/conf/redis.conf path/to/redis-master-slave slave.conf

修改配置

port 6379

port 6380

slaveof 127.0.0.1 6379

分别啟動兩個redis

redis-server path/to/redis-master-slave/master.conf

redis-server path/to/redis-master-slave/slave.conf

啟動之後,打開兩個指令行視窗,分别執行telnet localhost 6379 telnet localhost 6380

然後分别在兩個視窗中執行 info 指令,可以看到

主從配置沒問題。

然後在master 視窗執行 set 之後,到slave視窗執行get,可以get到,說明主從同步成功。

這時,我們如果在slave視窗執行 set ,會報錯:

因為從節點是隻讀的。

上面我們介紹了主從,從庫作為一個“傀儡”,可以在需要的時候“頂上來”,”接盤“。我們配置的主從是為了”有備無患“,在主redis挂了之後,可以立馬切換到從redis上,可能隻需要花幾分鐘的時間,但是仍然是需要人為操作。假設主redis在晚上23點挂了,10分鐘之後你接到電話,老闆讓你趕緊修複,于是你從被窩爬起來整,豈不是很頭疼。假如你關機了,又其他人知道伺服器密碼,那系統豈不是要停機一晚上?太可怕了。

這個時候redis sentinel 就派上用場了。sentinel 通常翻譯成哨兵,就是放哨的,這裡它就是用來監控主從節點的健康情況。用戶端連接配接redis主從的時候,先連接配接 sentinel,sentinel會告訴用戶端主redis的位址是多少,然後用戶端連接配接上redis并進行後續的操作。當主節點挂掉的時候,用戶端就得不到連接配接了因而報錯了,用戶端重新想sentinel詢問主master的位址,然後用戶端得到了[新選舉出來的主redis],然後又可以愉快的操作了。

為了說明sentinel的用處,我們做個試驗。配置3個redis(1主2從),1個哨兵。步驟如下:

上我們建立了 3個redis配置檔案,1個哨兵配置檔案。我們将 redis01設定為master,将redis02,redis03設定為slave。

上面的主從配置都熟悉,隻有哨兵配置 sentinel.conf,需要解釋一下:

上面我們配置好了redis主從,1主2從,以及1個哨兵。下面我們分别啟動redis,并啟動哨兵

啟動之後,可以分别連接配接到 3個redis上,執行info檢視主從資訊。

下面使用程式來連接配接哨兵,并操作redis。

程式非常簡單,循環運作20次,連接配接哨兵,将随機字元串 set到redis,get結果。列印資訊,異常捕獲。

運作上面的程式(注意,在實驗這個效果的時候,可以将sleep時間加長或者for循環增多,以防程式提前停止,不便看整體效果),然後将主redis關掉,模拟redis挂掉的情況。現在主redis為redis01,端口為63791

這個時候如果sentinel沒有設定背景運作,可以在指令行視窗看到 master切換的情況日志。

上面的日志較多,仔細找找可以看到下面幾行主要的:

這個日志比較晦澀,從代碼運作效果看,如下:

從結果看出

開始正常操作redis,并設定了兩次。

主redis挂了,jedis得不到連接配接,報錯了JedisConnectionException:Could not get a resource from the pool

主redis沒選好之前,程式持續報錯。

主redis選好了,程式正常運作,最後結束。

我們看到最後一次運作設定的值是aajhbjagag,我們可以連接配接剩下的2台redis中的任意一台,get hello,結果肯定是一緻的。

上面的章節中,我們分别學習了redis 單點,redis主從,并增加了高可用的 sentinel 哨兵模式。我們所做的這些工作隻是保證了資料備份以及高可用,目前為止我們的程式一直都是向1台redis寫資料,其他的redis隻是備份而已。實際場景中,單個redis節點可能不滿足要求,因為:

單個redis并發有限

單個redis接收所有的資料,最終回導緻記憶體太大,記憶體太大回導緻rdb檔案過大,從很大的rdb檔案中同步恢複資料會很慢。

所有,我們需要redis cluster 即redis叢集。

Redis 叢集是一個提供在多個Redis間節點間共享資料的程式集。

Redis叢集并不支援處理多個keys的指令,因為這需要在不同的節點間移動資料,進而達不到像Redis那樣的性能,在高負載的情況下可能會導緻不可預料的錯誤.

Redis 叢集通過分區來提供一定程度的可用性,在實際環境中當某個節點當機或者不可達的情況下繼續處理指令. Redis 叢集的優勢:

自動分割資料到不同的節點上。

整個叢集的部分節點失敗或者不可達的情況下能夠繼續處理指令。

為了配置一個redis cluster,我們需要準備至少6台redis,為啥至少6台呢?我們可以在redis的官方文檔中找到如下一句話:

因為最小的redis叢集,需要至少3個主節點,既然有3個主節點,而一個主節點搭配至少一個從節點,是以至少得6台redis。然而對我來說,就是複制6個redis配置檔案。本實驗的redis叢集搭建依然在一台電腦上模拟。

上面提到,配置redis叢集需要至少6個redis節點。是以我們需要準備及配置的節點如下:

上面的配置完成之後,分别啟動6個redis執行個體。配置正确的情況下,都可以啟動成功。然後運作如下指令建立叢集:

注意,這裡使用的是ip:port,而不是 domain:port ,因為我在使用 localhost:6371 之類的寫法執行的時候碰到錯誤:

執行成功之後,連接配接一台redis,執行 cluster info 會看到類似如下資訊:

我們可以看到cluster_state:ok,cluster_slots_ok:16384,cluster_size:3。

上面我們配置了一個redis叢集,包含6個redis節點,3主3從。下面我們來使用jedis來連接配接redis叢集。代碼如下:

上面我們設定了資訊set foo bar,但是不知道被設定到那一台redis上去了。請讀者思考一下,我們是叢集模式,是以資料被分散放到不同的槽中了,Redis 叢集有16384個哈希槽,每個key通過CRC16校驗後對16384取模來決定放置哪個槽.叢集的每個節點負責一部分hash槽,舉個例子,比如目前叢集有3個節點,那麼:

節點 A 包含 0 到 5500号哈希槽.

節點 B 包含5501 到 11000 号哈希槽.

節點 C 包含11001 到 16384号哈希槽.

看到這裡你應該還是不知道set foo bar 放到哪台redis上去了,不妨嘗試連接配接任意一台redis探索一下,你會知道的。

至此,我們了解并動手實踐了redis的安裝,redis單點,redis主從,redis 哨兵 sentinel,redis 叢集cluster。

我們來梳理一下redis主從,redis哨兵,redis機器的差別和關系。

redis主從:是備份關系, 我們操作主庫,資料也會同步到從庫。 如果主庫機器壞了,從庫可以上。就好比你 D盤的片丢了,但是你移動硬碟裡邊備份有。

redis哨兵:哨兵保證的是HA,保證特殊情況故障自動切換,哨兵盯着你的“redis主從叢集”,如果主庫死了,它會告訴你新的老大是誰。

redis叢集:叢集保證的是高并發,因為多了一些兄弟幫忙一起扛。同時叢集會導緻資料的分散,整個redis叢集會分成一堆資料槽,即不同的key會放到不不同的槽中。

主從保證了資料備份,哨兵保證了HA 即故障時切換,叢集保證了高并發性。

一切動手做了才會熟悉。

繼續閱讀