系統城裝機大師 - 唯一官網:www.farandoo.com!

當前位置:首頁 > 系統教程 > Linux教程 > 詳細頁面

Redis操作及集群搭建以及高可用配置

時間:2020-09-01來源:www.farandoo.com作者:電腦系統城


 
數據類型豐富 支持持久化 多種內存分配及回收策略 支持弱事務 支持高可用 支持分布式分片集群

3|0企業緩存產品介紹


 
Memcached: 優點:高性能讀寫、單一數據類型、支持客戶端式分布式集群、一致性hash 多核結構、多線程讀寫性能高。 缺點:無持久化、節點故障可能出現緩存穿透、分布式需要客戶端實現、跨機房數據同步困難、架構擴容復雜度高 Redis: 優點:高性能讀寫、多數據類型支持、數據持久化、高可用架構、支持自定義虛擬內存、支持分布式分片集群、單線程讀寫性能極高 缺點:多線程讀寫較Memcached慢 新浪、京東、直播類平臺、網頁游戲 memcache 與redis在讀寫性能的對比 memcached 適合,多用戶訪問,每個用戶少量的rw redis 適合,少用戶訪問,每個用戶大量rw Tair: 優點:高性能讀寫、支持三種存儲引擎(ddb、rdb、ldb)、支持高可用、支持分布式分片集群、支撐了幾乎所有淘寶業務的緩存。 缺點:單機情況下,讀寫性能較其他兩種產品較慢

4|0Redis使用場景介紹


 
Memcached:多核的緩存服務,更加適合于多用戶并發訪問次數較少的應用場景 Redis:單核的緩存服務,單節點情況下,更加適合于少量用戶,多次訪問的應用場景。 Redis一般是單機多實例架構,配合redis集群出現。

5|0Redis安裝部署:


 
下載: wget http://download.redis.io/releases/redis-3.2.12.tar.gz 解壓: 上傳至 /data tar xzf redis-3.2.12.tar.gz mv redis-3.2.12 redis 安裝: yum -y install gcc automake autoconf libtool make cd redis make 環境變量: vim /etc/profile export PATH=/data/redis/src:$PATH source /etc/profile 啟動: redis-server & 連接測試: redis-cli 127.0.0.1:6379> set num 10 OK 127.0.0.1:6379> get num 10

6|0Redis基本管理操作

6|1基礎配置文件介紹


 
mkdir /data/6379 cat > /data/6379/redis.conf<<EOF daemonize yes port 6379 logfile /data/6379/redis.log dir /data/6379 dbfilename dump.rdb EOF redis-cli shutdown redis-server /data/6379/redis.conf netstat -lnp|grep 63 +++++++++++配置文件說明++++++++++++++ redis.conf 是否后臺運行: daemonize yes 默認端口: port 6379 日志文件位置 logfile /var/log/redis.log 持久化文件存儲位置 dir /data/6379 RDB持久化數據文件: dbfilename dump.rdb ++++++++++++++++++++++++++++++++++++++ redis-cli 127.0.0.1:6379> set name zhangsan OK 127.0.0.1:6379> get name "zhangsan"

6|2redis安全配置


 
redis默認開啟了保護模式,只允許本地回環地址登錄并訪問數據庫。 禁止protected-mode protected-mode yes/no (保護模式,是否只允許本地訪問) (1)Bind :指定IP進行監聽 vim /data/6379/redis.conf bind 10.0.0.51 127.0.0.1 (2)增加requirepass {password} vim /data/6379/redis.conf requirepass 123456 ----------驗證----- 方法一: [root@db03 ~]# redis-cli -a 123456 127.0.0.1:6379> set name zhangsan OK 127.0.0.1:6379> exit 方法二: [root@db03 ~]# redis-cli 127.0.0.1:6379> auth 123456 OK 127.0.0.1:6379> set a b [root@db01 src]# redis-cli -a 123 -h 10.0.0.51 -p 6379 10.0.0.51:6379> set b 2 OK

6|3在線查看和修改配置


 
CONFIG GET * CONFIG GET requirepass CONFIG GET r* CONFIG SET requirepass 123

6|4redis持久化(內存數據保存到磁盤)


 
RDB、AOF RDB 持久化 可以在指定的時間間隔內生成數據集的 時間點快照(point-in-time snapshot)。 優點:速度快,適合于用做備份,主從復制也是基于RDB持久化功能實現的。 缺點:會有數據丟失 rdb持久化核心配置參數: vim /data/6379/redis.conf dir /data/6379 dbfilename dump.rdb save 900 1 save 300 10 save 60 10000 配置分別表示: 900秒(15分鐘)內有1個更改 300秒(5分鐘)內有10個更改 60秒內有10000個更改 AOF 持久化(append-only log file) 記錄服務器執行的所有寫操作命令,并在服務器啟動時,通過重新執行這些命令來還原數據集。 AOF 文件中的命令全部以 Redis 協議的格式來保存,新命令會被追加到文件的末尾。 優點:可以最大程度保證數據不丟 缺點:日志記錄量級比較大 AOF持久化配置 appendonly yes appendfsync always appendfsync everysec appendfsync no 是否打開aof日志功能 每1個命令,都立即同步到aof 每秒寫1次 寫入工作交給操作系統,由操作系統判斷緩沖區大小,統一寫入到aof. vim /data/6379/redis.conf appendonly yes appendfsync everysec 面試: redis 持久化方式有哪些?有什么區別? rdb:基于快照的持久化,速度更快,一般用作備份,主從復制也是依賴于rdb持久化功能 aof:以追加的方式記錄redis操作日志的文件??梢宰畲蟪潭鹊谋WCredis數據安全,類似于mysql的binlog

7|0Redis數據類型:


 
## 6.1 介紹 String : 字符類型 Hash: 字典類型 List: 列表 Set: 集合 Sorted set: 有序集合

7|1KEY的通用操作


 
KEYS * keys a keys a* 查看已存在所有鍵的名字 **** TYPE 返回鍵所存儲值的類型 **** EXPIRE\ PEXPIRE 以秒\毫秒設定生存時間 *** TTL\ PTTL 以秒\毫秒為單位返回生存時間 *** PERSIST 取消生存時間設置 *** DEL 刪除一個key EXISTS 檢查是否存在 RENAME 變更KEY名 ---例子: 127.0.0.1:6379> set name zhangsan 127.0.0.1:6379> EXPIRE name 60 (integer) 1 127.0.0.1:6379> ttl name (integer) 57 127.0.0.1:6379> set a b ex 60 OK 127.0.0.1:6379> ttl a 127.0.0.1:6379> PERSIST a (integer) 1 127.0.0.1:6379> ttl a (integer) -1

7|2Strings


 
應用場景 session 共享 常規計數:微博數,粉絲數,訂閱、禮物 key:value (1) set name zhangsan (2) MSET id 101 name zhangsan age 20 gender m 等價于以下操作: SET id 101 set name zhangsan set age 20 set gender m (3)計數器 每點一次關注,都執行以下命令一次 127.0.0.1:6379> incr num 顯示粉絲數量: 127.0.0.1:6379> get num 暗箱操作: 127.0.0.1:6379> INCRBY num 10000 (integer) 10006 127.0.0.1:6379> get num "10006" 127.0.0.1:6379> DECRBY num 10000 (integer) 6 127.0.0.1:6379> get num "6"

7|3hash類型(字典類型)


 
應用場景: 存儲部分變更的數據,如用戶信息等。 最接近mysql表結構的一種類型 主要是可以做數據庫緩存。 存數據: hmset stu id 101 name zhangsan age 20 gender m hmset stu1 id 102 name zhangsan1 age 21 gender f 取數據: HMGET stu id name age gender HMGET stu1 id name age gender select concat("hmset city_",id," id ",id," name ",name) from world.city limit 10 into outfile '/tmp/hmset.txt'

7|4LIST(列表)


 
應用場景 消息隊列系統 比如sina微博 在Redis中我們的最新微博ID使用了常駐緩存,這是一直更新的。 但是做了限制不能超過5000個ID,因此獲取ID的函數會一直詢問Redis。 只有在start/count參數超出了這個范圍的時候,才需要去訪問數據庫。 系統不會像傳統方式那樣“刷新”緩存,Redis實例中的信息永遠是一致的。 SQL數據庫(或是硬盤上的其他類型數據庫)只是在用戶需要獲取“很遠”的數據時才會被觸發, 而主頁或第一個評論頁是不會麻煩到硬盤上的數據庫了。 微信朋友圈: LPUSH wechat "today is 1 !" LPUSH wechat "today is 2 !" LPUSH wechat "today is 3 !" LPUSH wechat "today is 4 !" LPUSH wechat "today is 5 !" [5,4,3,2,1] 0 1 2 3 4 [e,d,c,b,a] 0 1 2 3 4 127.0.0.1:6379> lrange wechat 0 0 1) "today is friday !" 127.0.0.1:6379> lrange wechat 0 1 1) "today is friday !" 2) "today is rainy day !" 127.0.0.1:6379> lrange wechat 0 2 1) "today is friday !" 2) "today is rainy day !" 3) "today is good day !" 127.0.0.1:6379> lrange wechat 0 3 127.0.0.1:6379> lrange wechat -2 -1 1) "today is bad day !" 2) "today is nice day !"

7|5SET 集合類型(join union)


 
應用場景: 案例:在微博應用中,可以將一個用戶所有的關注人存在一個集合中,將其所有粉絲存在一個集合。 Redis還為集合提供了求交集、并集、差集等操作,可以非常方便的實現如共同關注、共同喜好、二度好友等功能, 對上面的所有集合操作,你還可以使用不同的命令選擇將結果返回給客戶端還是存集到一個新的集合中。 127.0.0.1:6379> sadd lxl pg1 jnl baoqiang gsy alexsb (integer) 5 127.0.0.1:6379> sadd jnl baoqiang ms bbh yf wxg (integer) 5 .... 127.0.0.1:6379> SUNION lxl jnl 1) "baoqiang" 2) "yf" 3) "bbh" 4) "ms" 5) "wxg" 127.0.0.1:6379> SUNION lxl jnl 1) "gsy" 2) "yf" 3) "alexsb" 4) "bbh" 5) "jnl" 6) "pg1" 7) "baoqiang" 8) "ms" 9) "wxg" 127.0.0.1:6379> ...... 127.0.0.1:6379> SINTER lxl jnl 1) "baoqiang" ........ 127.0.0.1:6379> SDIFF jnl lxl 1) "wxg" 2) "yf" 3) "bbh" 4) "ms" 127.0.0.1:6379> 127.0.0.1:6379> SDIFF lxl jnl 1) "jnl" 2) "pg1" 3) "gsy" 4) "alexsb" .....

7|6SortedSet(有序集合)


 
應用場景: 排行榜應用,取TOP N操作 這個需求與上面需求的不同之處在于,前面操作以時間為權重,這個是以某個條件為權重,比如按頂的次數排序, 這時候就需要我們的sorted set出馬了,將你要排序的值設置成sorted set的score,將具體的數據設置成相應的value,每次只需要執行一條ZADD命令即可。 127.0.0.1:6379> zadd topN 0 smlt 0 fskl 0 fshkl 0 lzlsfs 0 wdhbx 0 wxg (integer) 6 127.0.0.1:6379> ZINCRBY topN 100000 smlt "100000" 127.0.0.1:6379> ZINCRBY topN 10000 fskl "10000" 127.0.0.1:6379> ZINCRBY topN 1000000 fshkl "1000000" 127.0.0.1:6379> ZINCRBY topN 100 lzlsfs "100" 127.0.0.1:6379> ZINCRBY topN 10 wdhbx "10" 127.0.0.1:6379> ZINCRBY topN 100000000 wxg "100000000" 127.0.0.1:6379> ZREVRANGE topN 0 2 1) "wxg" 2) "fshkl" 3) "smlt" 127.0.0.1:6379> ZREVRANGE topN 0 2 withscores 1) "wxg" 2) "100000000" 3) "fshkl" 4) "1000000" 5) "smlt" 6) "100000" 127.0.0.1:6379>

8|0Redis事務


 
redis的事務是基于隊列實現的。 mysql的事務是基于事務日志和鎖機制實現的。 redis是樂觀鎖機制。 開啟事務功能時(multi) multi command1 command2 command3 command4 exec discard 4條語句作為一個組,并沒有真正執行,而是被放入同一隊列中。 如果,這時執行discard,會直接丟棄隊列中所有的命令,而不是做回滾。 exec 當執行exec時,對列中所有操作,要么全成功要么全失敗 127.0.0.1:6379> set a b OK 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> set a b QUEUED 127.0.0.1:6379> set c d QUEUED 127.0.0.1:6379> exec 1) OK 2) OK

9|0redis(Master-Replicaset) *****

9|1原理:


 
1. 副本庫通過slaveof 10.0.0.51 6379命令,連接主庫,并發送SYNC給主庫 2. 主庫收到SYNC,會立即觸發BGSAVE,后臺保存RDB,發送給副本庫 3. 副本庫接收后會應用RDB快照 4. 主庫會陸續將中間產生的新的操作,保存并發送給副本庫 5. 到此,我們主復制集就正常工作了 6. 再此以后,主庫只要發生新的操作,都會以命令傳播的形式自動發送給副本庫. 7. 所有復制相關信息,從info信息中都可以查到.即使重啟任何節點,他的主從關系依然都在. 8. 如果發生主從關系斷開時,從庫數據沒有任何損壞,在下次重連之后,從庫發送PSYNC給主庫 9. 主庫只會將從庫缺失部分的數據同步給從庫應用,達到快速恢復主從的目的

9|2主從數據一致性保證


 
min-slaves-to-write 1 min-slaves-max-lag 3

9|3主庫是否要開啟持久化?


 
如果不開有可能,主庫重啟操作,造成所有主從數據丟失!

10|0主從復制實現


 
1、環境: 準備兩個或兩個以上redis實例 mkdir /data/638{0..2} 配置文件示例: cat >> /data/6380/redis.conf <<EOF port 6380 daemonize yes pidfile /data/6380/redis.pid loglevel notice logfile "/data/6380/redis.log" dbfilename dump.rdb dir /data/6380 requirepass 123 masterauth 123 EOF cat >> /data/6381/redis.conf <<EOF port 6381 daemonize yes pidfile /data/6381/redis.pid loglevel notice logfile "/data/6381/redis.log" dbfilename dump.rdb dir /data/6381 requirepass 123 masterauth 123 EOF cat >> /data/6382/redis.conf <<EOF port 6382 daemonize yes pidfile /data/6382/redis.pid loglevel notice logfile "/data/6382/redis.log" dbfilename dump.rdb dir /data/6382 requirepass 123 masterauth 123 EOF 啟動: redis-server /data/6380/redis.conf redis-server /data/6381/redis.conf redis-server /data/6382/redis.conf 主節點:6380 從節點:6381、6382 2、開啟主從: 6381/6382命令行: redis-cli -p 6381 -a 123 SLAVEOF 127.0.0.1 6380 redis-cli -p 6382 -a 123 SLAVEOF 127.0.0.1 6380 3、查詢主從狀態 redis-cli -p 6380 -a 123 info replication

11|0redis-sentinel(哨兵)


 
1、監控 2、自動選主,切換(6381 slaveof no one) 采用的是raft分布式一致性協議進行選主:數據節接近主,可以和大部分節點聯系,少數服從多數。 3、重構主從管理 4、應用透明 5、自動處理故障節點 sentinel搭建過程 mkdir /data/26380 cd /data/26380 vim sentinel.conf port 26380 dir "/data/26380" sentinel monitor mymaster 127.0.0.1 6380 1 sentinel down-after-milliseconds mymaster 5000 sentinel auth-pass mymaster 123 啟動: [root@db01 26380]# redis-sentinel /data/26380/sentinel.conf &>/tmp/sentinel.log &

12|0cluster集群搭建]

以前要搞redis集群,得借助一致性hash來自己搞sharding,現在方便多了,直接上cluster功能就行了,而且還支持節點動態添加、HA、節點增減后緩存重新分布(resharding)。

下面是參考官方教程cluster-tutorial 在mac機上搭建cluster的過程:

一、下載最新版redis 編譯

目前最新版是3.0.7,下載地址:http://www.redis.io/download

編譯很簡單,一個make命令即可

二、建6個目錄


 
mkdir ~/app/redis-cluster/ #先建一個根目錄 mkdir 7000 7001 7002 7003 7004 7005

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

然后把步驟1里編譯好的redis,復制到這6個目錄下。

三、配置文件


 
port 7000 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes

把上面這段保存成redis-cluster.conf,放到每個目錄的redis目錄中,注意修改port端口,即7000目錄下的port為7000,7001目錄下的port為7001...

cluster-node-timeout 是集群中各節點相互通訊時,允許"失聯"的最大毫秒數,上面的配置為5秒,如果超過5秒某個節點沒向其它節點匯報成功,認為該節點掛了。

四、依次啟動各個redis

在每個目錄redis的src子目錄下,輸入:


 
./redis-server ../redis-cluster.conf

這樣7000~7005這6個節點就啟動了。

五、安裝redis的ruby模塊


 
brew update brew install ruby sudo gem install redis #注:這個步驟建議翻^墻

解釋:雖然步驟4把6個redis server啟動成功了,但是彼此之間是完全獨立的,需要借助其它工具將其加入cluster,而這個工具就是redis提供的一個名為redis-trib.rb的ruby腳本(個人估計redis的作者比較偏愛ruby),mac自帶了ruby2.0環境,但是沒有redis模塊,所以要安裝這玩意兒,否則接下來的創建cluster將失敗。

六、創建cluster


 
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 \ 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

仍然保持在某個目錄的src子目錄下,運行上面這段shell腳本,cluster就創建成功了,replicas 1的意思,就是每個節點創建1個副本(即:slave),所以最終的結果,就是后面的127.0.0.1:7000~127.0.0.1:7005中,會有3個會指定成master,而其它3個會指定成slave。

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

此時,如何用ps查看redis進程,會看到每個進程后附帶了cluster的字樣

點擊看大圖

如果想知道,哪些端口的節點是master,哪些端口的節點是slave,可以用下面的命令:


 
./redis-trib.rb check 127.0.0.1:7000

輸出結果如下:


 
>>> Performing Cluster Check (using node 127.0.0.1:7000) S: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e 127.0.0.1:7000 slots: (0 slots) slave replicates 38910c5baafea02c5303505acfd9bd331c608cfc M: e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa 127.0.0.1:7001 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: 88e16f91609c03277f2ee6ce5285932f58c221c1 127.0.0.1:7005 slots: (0 slots) slave replicates ec964a7c7cd53b986f54318a190c1426fc53a5fa S: be7e9fd3b7d096b037306bc14e1017150fa59d7a 127.0.0.1:7004 slots: (0 slots) slave replicates e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa M: 38910c5baafea02c5303505acfd9bd331c608cfc 127.0.0.1:7003 slots:0-5460 (5461 slots) master 1 additional replica(s) M: ec964a7c7cd53b986f54318a190c1426fc53a5fa 127.0.0.1:7002 slots:10923-16383 (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.

從上面的輸出,可以看出7000、7004、7005是slave,而7001、7003、7002是master(如果大家人為做過一些failover的測試,比如把某個節點手動停掉,再恢復,輸出的結果可能與上面不太一樣),除了check參數,還有一個常用的參數info


 
./redis-trib.rb info 127.0.0.1:7000

輸出結果如下:


 
127.0.0.1:7001 (e0e8dfdd...) -> 2 keys | 5462 slots | 1 slaves. 127.0.0.1:7003 (38910c5b...) -> 2 keys | 5461 slots | 1 slaves. 127.0.0.1:7002 (ec964a7c...) -> 0 keys | 5461 slots | 1 slaves. [OK] 4 keys in 3 masters. 0.00 keys per slot on average.

它會把所有的master信息輸出,包括這個master上有幾個緩存key,有幾個slave,所有master上的keys合計,以及平均每個slot上有多少key,想了解更多redis-trib腳本的其它參數,可以用


 
./redis-trib.rb help

輸出如下:


 
Usage: redis-trib <command> <options> <arguments ...> create host1:port1 ... hostN:portN --replicas <arg> check host:port info host:port fix host:port --timeout <arg> reshard host:port --from <arg> --to <arg> --slots <arg> --yes --timeout <arg> --pipeline <arg> rebalance host:port --weight <arg> --auto-weights --use-empty-masters --timeout <arg> --simulate --pipeline <arg> --threshold <arg> add-node new_host:new_port existing_host:existing_port --slave --master-id <arg> del-node host:port node_id set-timeout host:port milliseconds call host:port command arg arg .. arg import host:port --from <arg> --copy --replace help (show this help) For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.

上面已經多次出現了slot這個詞,略為解釋一下:

點擊看大圖

如上圖,redis-cluster把整個集群的存儲空間劃分為16384個slot(譯為:插槽?),當6個節點分為3主3從時,相當于整個cluster中有3組HA的節點,3個master會平均分攤所有slot,每次向cluster中的key做操作時(比如:讀取/寫入緩存),redis會對key值做CRC32算法處理,得到一個數值,然后再對16384取模,通過余數判斷該緩存項應該落在哪個slot上,確定了slot,也就確定了保存在哪個master節點上,當cluster擴容或刪除節點時,只需要將slot重新分配即可(即:把部分slot從一些節點移動到其它節點)。

七、redis-cli客戶端操作


 
./redis-cli -c -h localhost -p 7000

注意加參數-c,表示進入cluster模式,隨便添加一個緩存試試:


 
localhost:7000> set user1 jimmy -> Redirected to slot [8106] located at 127.0.0.1:7001 OK

注意第2行的輸出,表示user1這個緩存通過計算后,落在8106這個slot上,最終定位在7001這個端口對應的節點上(解釋:因為7000是slave,7001才是master,只有master才能寫入),如果是在7001上重復上面的操作時,不會出現第2行(解釋:7001是master,所以不存在redirect的過程)


 
? src ./redis-cli -c -h localhost -p 7001 localhost:7001> set user1 yang OK localhost:7001>

八、FailOver測試

先用redis-trib.rb 查看下當前的主、從情況


 
? src ./redis-trib.rb check localhost:7000 >>> Performing Cluster Check (using node localhost:7000) S: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e localhost:7000 slots: (0 slots) slave replicates 38910c5baafea02c5303505acfd9bd331c608cfc M: ec964a7c7cd53b986f54318a190c1426fc53a5fa 127.0.0.1:7002 slots:10923-16383 (5461 slots) master 1 additional replica(s) M: e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa 127.0.0.1:7001 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: be7e9fd3b7d096b037306bc14e1017150fa59d7a 127.0.0.1:7004 slots: (0 slots) slave replicates e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa S: 88e16f91609c03277f2ee6ce5285932f58c221c1 127.0.0.1:7005 slots: (0 slots) slave replicates ec964a7c7cd53b986f54318a190c1426fc53a5fa M: 38910c5baafea02c5303505acfd9bd331c608cfc 127.0.0.1:7003 slots:0-5460 (5461 slots) master 1 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.

從輸出上看7000是7003(38910c5baafea02c5303505acfd9bd331c608cfc)的slave,現在我們人工把7003的redis進程給kill掉,然后觀察7000的終端輸出:


 
872:S 21 Mar 10:55:55.663 * Connecting to MASTER 127.0.0.1:7003 3872:S 21 Mar 10:55:55.663 * MASTER <-> SLAVE sync started 3872:S 21 Mar 10:55:55.663 # Error condition on socket for SYNC: Connection refused 3872:S 21 Mar 10:55:55.771 * Marking node 38910c5baafea02c5303505acfd9bd331c608cfc as failing (quorum reached). 3872:S 21 Mar 10:55:55.771 # Cluster state changed: fail 3872:S 21 Mar 10:55:55.869 # Start of election delayed for 954 milliseconds (rank #0, offset 183). 3872:S 21 Mar 10:55:56.703 * Connecting to MASTER 127.0.0.1:7003 3872:S 21 Mar 10:55:56.703 * MASTER <-> SLAVE sync started 3872:S 21 Mar 10:55:56.703 # Error condition on socket for SYNC: Connection refused 3872:S 21 Mar 10:55:56.909 # Starting a failover election for epoch 10. 3872:S 21 Mar 10:55:56.911 # Failover election won: I'm the new master. 3872:S 21 Mar 10:55:56.911 # configEpoch set to 10 after successful failover 3872:M 21 Mar 10:55:56.911 * Discarding previously cached master state. 3872:M 21 Mar 10:55:56.911 # Cluster state changed: ok

注意5,6,11這幾行,第5行表明由于7003宕機,cluster狀態已經切換到fail狀態,第6行表示發起選舉,第11行表示7000端口對應的節點當選為new master。

注:如果一組分片中的master、slave全掛了,整個cluster集群不再接受任何讀/寫指令,redis-cli終端里會直接報cluster down,但是info等其它指令仍然可用,直到這一組分片中,有一個節點恢復為止。

九、cluster 擴容

業務規模變大后,集群擴容是早晚的事情,下面演示如何再添加2個節點,先把7000復制二份,變成7006,7007,然后進入7006/7007目錄redis的src子目錄下


 
rm nodes.conf dump.rdb appendonly.aof

由于7000我們剛才啟動過,里面有已經有一些數據了,所以要把數據文件,日志文件,以及cluster的nodes.conf文件刪除,變成一個空的redis獨立節點,否則無法加入cluster。

然后修改redis-cluster.conf


 
port 7000 cluster-enabled yes cluster-config-file "nodes.conf" cluster-node-timeout 10000 appendonly yes # Generated by CONFIG REWRITE dir "/Users/yjmyzz/app/redis-cluster/7000/redis-3.0.7/src"

要修改的地方有二處,1是第一行的端口,改成與7006/7007匹配的端口,2是最后2行,這是7000運行后,自動添加的,把最后二行刪除。

做完這些后,啟動7006,7007這二個redis節點,此時這2個新節點與cluster沒有任何關系,可以用下面的命令將7006做為master添加到cluster中。


 
./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000

注:第1個參數為新節點的"IP:端口",第2個參數為集群中的任一有效的節點。

順利的話,輸出如下:


 
>>> Adding node 127.0.0.1:7006 to cluster 127.0.0.1:7000 >>> Performing Cluster Check (using node 127.0.0.1:7000) M: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e 127.0.0.1:7000 slots:0-5460 (5461 slots) master 1 additional replica(s) M: e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa 127.0.0.1:7001 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: be7e9fd3b7d096b037306bc14e1017150fa59d7a 127.0.0.1:7004 slots: (0 slots) slave replicates e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa M: ec964a7c7cd53b986f54318a190c1426fc53a5fa 127.0.0.1:7002 slots:10923-16383 (5461 slots) master 1 additional replica(s) S: 88e16f91609c03277f2ee6ce5285932f58c221c1 127.0.0.1:7005 slots: (0 slots) slave replicates ec964a7c7cd53b986f54318a190c1426fc53a5fa S: 38910c5baafea02c5303505acfd9bd331c608cfc 127.0.0.1:7003 slots: (0 slots) slave replicates 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. >>> Send CLUSTER MEET to node 127.0.0.1:7006 to make it join the cluster. [OK] New node added correctly.

可以再用check確認下狀態:


 
? src ./redis-trib.rb check 127.0.0.1:7000 >>> Performing Cluster Check (using node 127.0.0.1:7000) M: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e 127.0.0.1:7000 slots:0-5460 (5461 slots) master 1 additional replica(s) M: e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa 127.0.0.1:7001 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: be7e9fd3b7d096b037306bc14e1017150fa59d7a 127.0.0.1:7004 slots: (0 slots) slave replicates e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa M: 226d1af3c95bf0798ea9fed86373b89347f889da 127.0.0.1:7006 slots: (0 slots) master 0 additional replica(s) M: ec964a7c7cd53b986f54318a190c1426fc53a5fa 127.0.0.1:7002 slots:10923-16383 (5461 slots) master 1 additional replica(s) S: 88e16f91609c03277f2ee6ce5285932f58c221c1 127.0.0.1:7005 slots: (0 slots) slave replicates ec964a7c7cd53b986f54318a190c1426fc53a5fa S: 38910c5baafea02c5303505acfd9bd331c608cfc 127.0.0.1:7003 slots: (0 slots) slave replicates 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.

12-14行說明7006已經是cluster的新master了,繼續,用下面的命令把7007當成slave加入:


 
./redis-trib.rb add-node --slave --master-id 226d1af3c95bf0798ea9fed86373b89347f889da 127.0.0.1:7007 127.0.0.1:7000

這里多出了二個參數:--slave 表示準備將新節點當成slave加入,--master-id xxxxx 則是指定要當誰的slave,后面的xxx部分,即為前面check的輸出結果中,7006的ID,完事之后,可以再次確認狀態:


 
? src ./redis-trib.rb check 127.0.0.1:7000 >>> Performing Cluster Check (using node 127.0.0.1:7000) M: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e 127.0.0.1:7000 slots:0-5460 (5461 slots) master 1 additional replica(s) S: 792bcccf35845c4922dd33d7f9827420ebb89bc9 127.0.0.1:7007 slots: (0 slots) slave replicates 226d1af3c95bf0798ea9fed86373b89347f889da M: e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa 127.0.0.1:7001 slots:5461-10922 (5462 slots) master 1 additional replica(s) S: be7e9fd3b7d096b037306bc14e1017150fa59d7a 127.0.0.1:7004 slots: (0 slots) slave replicates e0e8dfddd4e9d855090d6efd18e55ea9c0e1f7aa M: 226d1af3c95bf0798ea9fed86373b89347f889da 127.0.0.1:7006 slots: (0 slots) master 1 additional replica(s) M: ec964a7c7cd53b986f54318a190c1426fc53a5fa 127.0.0.1:7002 slots:10923-16383 (5461 slots) master 1 additional replica(s) S: 88e16f91609c03277f2ee6ce5285932f58c221c1 127.0.0.1:7005 slots: (0 slots) slave replicates ec964a7c7cd53b986f54318a190c1426fc53a5fa S: 38910c5baafea02c5303505acfd9bd331c608cfc 127.0.0.1:7003 slots: (0 slots) slave replicates 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.

觀察6-8行、15-17行,說明7007已經是7006的slave。

十、reshard 重新劃分slot

增加新的節點之后,問題就來了,16384個slot已經被其它3組節點分完了,新節點沒有slot,沒辦法存放緩存,所以需要將slot重新分布。


 
? src ./redis-trib.rb info 127.0.0.1:7000 127.0.0.1:7000 (0b7e0d53...) -> 4 keys | 5461 slots | 1 slaves. 127.0.0.1:7001 (e0e8dfdd...) -> 4 keys | 5462 slots | 1 slaves. 127.0.0.1:7006 (226d1af3...) -> 0 keys | 0 slots | 1 slaves. #7006上完全沒有slot 127.0.0.1:7002 (ec964a7c...) -> 9 keys | 5461 slots | 1 slaves. [OK] 17 keys in 4 masters. 0.00 keys per slot on average.

用下面的命令可以重新分配slot


 
./redis-trib.rb reshard 127.0.0.1:7000

reshard后面的IP:port,只要是在cluster中的有效節點即可。


 
? src ./redis-trib.rb reshard 127.0.0.1:7000 >>> Performing Cluster Check (using node 127.0.0.1:7000) M: 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e 127.0.0.1:7000 slots:1792-4095 (2304 slots) master 0 additional replica(s) ... [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. How many slots do you want to move (from 1 to 16384)? 1000 #這里輸入要移動多少slot What is the receiving node ID? 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e #這里輸入目標節點的id Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1:all #將所有node都當成源節點 ... Moving slot 4309 from ec964a7c7cd53b986f54318a190c1426fc53a5fa Moving slot 4310 from ec964a7c7cd53b986f54318a190c1426fc53a5fa Moving slot 4311 from ec964a7c7cd53b986f54318a190c1426fc53a5fa Moving slot 4312 from ec964a7c7cd53b986f54318a190c1426fc53a5fa Moving slot 4313 from ec964a7c7cd53b986f54318a190c1426fc53a5fa Do you want to proceed with the proposed reshard plan (yes/no)? yes #確認執行

注:第一個交互詢問,填寫多少slot移動時,要好好想想,如果填成16384,則將所有slot都移動到一個固定節點上,會導致更加不均衡!建議每次移動500~1000,這樣對線上的影響比較小。

另外在填寫source node時,除了all之外,還可以直接填寫源節點的id,即:


 
[OK] All 16384 slots covered. How many slots do you want to move (from 1 to 16384)? 300 What is the receiving node ID? 0b7e0d5337e87ac7b59bba4c1248e5c9e8d1905e Please enter all the source node IDs. Type 'all' to use all the nodes as source nodes for the hash slots. Type 'done' once you entered all the source nodes IDs. Source node #1:226d1af3c95bf0798ea9fed86373b89347f889da #這里填寫源節點的id Source node #2:done #這里輸入done表示,不再繼續添加源節點了

reshard可以多次操作,直到達到期望的分布為止(注:個人覺得redis的reshard這里有點麻煩,要移動多少slot需要人工計算,如果能提供一個參數之類,讓16384個slot自動平均分配就好了),調整完成后,可以再看看分布情況:


 
? src ./redis-trib.rb info 127.0.0.1:7000 127.0.0.1:7000 (0b7e0d53...) -> 4 keys | 4072 slots | 0 slaves. 127.0.0.1:7001 (e0e8dfdd...) -> 5 keys | 4099 slots | 0 slaves. 127.0.0.1:7006 (226d1af3...) -> 5 keys | 4132 slots | 4 slaves. 127.0.0.1:7002 (ec964a7c...) -> 3 keys | 4081 slots | 0 slaves. [OK] 17 keys in 4 masters. 0.00 keys per slot on average.

十一、刪除節點del-node

既然有擴容,就會有反向需求,某些節點不再需要時,可以用del-node刪除,比如剛才我一陣亂倒騰后,發現7006已經有4個slave了,而其它master一個slave都沒有,這明顯不合理。

刪除節點命令:


 
./redis-trib.rb del-node 127.0.0.1:7006 88e16f91609c03277f2ee6ce5285932f58c221c1

del-node后面的ip:port只要是cluster中有效節點即可,最后一個參數為目標節點的id,注意:只有slave節點和空的master節點可以刪除,如果master非空,先用reshard把上面的slot移動到其它node后再刪除,如果有一組master-slave節點,將master上所有slot移到其它節點,然后將master刪除,剩下的slave會另尋他主,變成其它master的slave。

另外:刪除節點的含義,不僅僅是從cluster中將這個節點移除,還會直接將目標節點的redis服務停止。

分享到:

相關信息

系統教程欄目

欄目熱門教程

人氣教程排行

站長推薦

熱門系統下載

jlzzjlzz亚洲乱熟在线播放