<meta charset="utf-8">
第1章 Redis介紹
1.1 Redis是什么
Redis是一種基于鍵值對的NoSQL數(shù)據(jù)庫,與很多鍵值對數(shù)據(jù)庫不同,redis中的值可以有string,hash,list,set,zset,geo等多種數(shù)據(jù)結(jié)構(gòu)和算法組成.
因?yàn)镽edis會(huì)將所有的數(shù)據(jù)都放在內(nèi)存中,所以他的讀寫性能非常驚人.
不僅如此,Redis還可以將內(nèi)存中的數(shù)據(jù)利用快照和日志的形式保存到硬盤上
Redis還提供了鍵過期,發(fā)布訂閱,事務(wù),流水線等附加功能.
1.2 Redis重要特性
1.速度快
Redis所有的數(shù)據(jù)都存放在內(nèi)存中
Redis使用C語言實(shí)現(xiàn)
Redis使用單線程架構(gòu)
2.基于鍵值對的數(shù)據(jù)結(jié)構(gòu)服務(wù)器
5中數(shù)據(jù)結(jié)構(gòu):字符串,哈希,列表,集合,有序集合
3.豐富的功能
提供了鍵過期功能,可以實(shí)現(xiàn)緩存
提供了發(fā)布訂閱功能,可以實(shí)現(xiàn)消息系統(tǒng)
提供了pipeline功能,客戶端可以將一批命令一次性傳到Redis,減少了網(wǎng)絡(luò)開銷
4.簡單穩(wěn)定
源碼很少,3.0版本以后5萬行左右.
使用單線程模型法,是的Redis服務(wù)端處理模型變得簡單.
不依賴操作系統(tǒng)的中的類庫
5.客戶端語言多
java,PHP,python,C,C++,Nodejs等
6.持久化
RDB和AOF
7.主從復(fù)制
8.高可用和分布式
哨兵
集群
1.3 Redis應(yīng)用場景
1.緩存-鍵過期時(shí)間
緩存session會(huì)話
緩存用戶信息,找不到再去mysql查,查到然后回寫到redis
2.排行榜-列表&有序集合
熱度排名排行榜
發(fā)布時(shí)間排行榜
3.計(jì)數(shù)器應(yīng)用-天然支持計(jì)數(shù)器
帖子瀏覽數(shù)
視頻播放次數(shù)
商品瀏覽數(shù)
4.社交網(wǎng)絡(luò)-集合
踩/贊,粉絲,共同好友/喜好,推送,打標(biāo)簽
5.消息隊(duì)列系統(tǒng)-發(fā)布訂閱
配合elk實(shí)現(xiàn)日志收集
第2章 Redis安裝部署
2.1 目錄規(guī)劃
### redis下載目錄
/data/soft/
### redis安裝目錄
/opt/redis_cluster/redis_{PORT}/{conf,logs,pid}
### redis數(shù)據(jù)目錄
/data/redis_cluster/redis_{PORT}/redis_{PORT}.rdb
### redis運(yùn)維腳本
/root/scripts/redis_shell.sh
2.2 安裝命令
編輯hosts文件
[root@db01 ~]# tail -3 /etc/hosts
10.0.0.51 db01
10.0.0.52 db02
10.0.0.53 db03
mkdir -p /data/soft
mkdir -p /data/redis_cluster/redis_6379
mkdir -p /opt/redis_cluster/redis_6379/{conf,pid,logs}
cd /data/soft/
wget http://download.redis.io/releases/redis-3.2.9.tar.gz
tar zxf redis-3.2.9.tar.gz -C /opt/redis_cluster/
ln -s /opt/redis_cluster/redis-3.2.9/ /opt/redis_cluster/redis
cd /opt/redis_cluster/redis
make && make install
2.3 配置文件說明
### 以守護(hù)進(jìn)程模式啟動(dòng)
daemonize yes
### 綁定的主機(jī)地址
bind 10.0.0.51
### 監(jiān)聽端口
port 6379
### pid文件和log文件的保存地址
pidfile /opt/redis_cluster/redis_6379/pid/redis_6379.pid
logfile /opt/redis_cluster/redis_6379/logs/redis_6379.log
### 設(shè)置數(shù)據(jù)庫的數(shù)量郭膛,默認(rèn)數(shù)據(jù)庫為0
databases 16
### 指定本地持久化文件的文件名,默認(rèn)是dump.rdb
dbfilename redis_6379.rdb
### 本地?cái)?shù)據(jù)庫的目錄
dir /data/redis_cluster/redis_6379
2.4 啟動(dòng)關(guān)閉服務(wù)
啟動(dòng)
[root@db01 ~]# redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf
關(guān)閉
[root@db01 ~]# redis-cli -h db01 shutdown
第3章 Redis基本操作命令
3.1 全局命令
Redis有5種數(shù)據(jù)結(jié)構(gòu),他們是鍵值對中的值,對于鍵來說有一些通用的命令.
1.查看所有命鍵
Keys *
十分危險(xiǎn)的命令,線上禁止使用
2.查看鍵的總數(shù)
Dbsize
# dbsize 命令在計(jì)算鍵總數(shù)時(shí)不會(huì)遍歷所有鍵,而是直接獲取Redis內(nèi)置的鍵總數(shù)變量.
3.檢查鍵是否存在
Exists key
# 如果鍵存在則返回1,不存在則返回0
4.刪除鍵
Del key [key …]
通用命令,無論值是什么數(shù)據(jù)結(jié)構(gòu)類型,del命令都可以將其刪除.
5.鍵過期
Expire key seconds
# Redis支持對鍵添加過期時(shí)間,當(dāng)超過過期時(shí)間后,會(huì)自動(dòng)刪除鍵.
# 通過ttl命令觀察鍵的剩余時(shí)間
大于等于0的證書: 鍵剩余過期時(shí)間
-1: 鍵沒設(shè)置過期時(shí)間
-2: 鍵不存在
6.鍵的數(shù)據(jù)類型
Type key
3.2 字符串
Redis并不是簡單地key-value存儲(chǔ),實(shí)際上他是一個(gè)數(shù)據(jù)結(jié)構(gòu)服務(wù)器,支持不同類型的值.
Redis Strings
這是最簡單的Redis類型,如果你只用這種類型,Redis就像一個(gè)持久化的memcache服務(wù)器(注:memcache的數(shù)據(jù)僅保存在內(nèi)存中,服務(wù)器重啟后,數(shù)據(jù)將丟失.)
操作命令:
通常用SET command 和 GET command來設(shè)置和獲取字符串值
練習(xí):
db01:6379> set key1 value1
OK
db01:6379> get key1
"value1"
db01:6379> keys *
1) "key1"
操作命令:
INCR命令將字符串值解析成整型.將其加1,最后結(jié)果保存為新的字符串,類似命令: INCRBY,DECR,DECRBY
練習(xí):
db01:6379> set key2 100
OK
db01:6379> get key2
"100"
db01:6379> incr key2
(integer) 101
db01:6379> get key2
"101"
db01:6379> incrby key2 10
(integer) 111
db01:6379> get key2
"111"
操作命令:
MSET和MGET可以一次存儲(chǔ)或獲取多個(gè)key對應(yīng)的值.
練習(xí):
db01:6379> mset key3 v3 key4 v4 key5 v5
OK
db01:6379> mget key3 key4 key5
1) "v3"
2) "v4"
3) "v5"
操作命令:
EXISTS命令返回1或0標(biāo)識(shí)給定key的值是否存在.
使用DEL命令可以刪除key對應(yīng)的值,
DEL命令返回1或0標(biāo)識(shí)是被刪除(值存在)或者沒被刪除(key對應(yīng)的值不存在).
練習(xí):
db01:6379> exists key5
(integer) 1
db01:6379> del key5
(integer) 1
db01:6379> exists key5
(integer) 0
db01:6379> del key5
(integer) 0
操作命令:
Type命令可以返回key對應(yīng)的存儲(chǔ)類型
練習(xí):
db01:6379> set key5 v5
OK
db01:6379> type key5
string
操作命令:
可以對key設(shè)置一個(gè)超時(shí)時(shí)間,當(dāng)這個(gè)時(shí)間到達(dá)后被刪除
練習(xí):
db01:6379> get key5
"v5"
db01:6379> ttl key5
(integer) -1
db01:6379> expire key5 10
(integer) 1
db01:6379> ttl key5
(integer) 6
db01:6379> ttl key5
(integer) 5
db01:6379> ttl key5
(integer) 2
db01:6379> ttl key5
(integer) -2
db01:6379> ttl key5
(integer) -2
db01:6379> get key5
(nil)
操作命令:
PERSIST命令去除超時(shí)時(shí)間
練習(xí):
db01:6379> set key5 v5 ex 10
OK
db01:6379> ttl key5
(integer) 8
db01:6379> ttl key5
(integer) 6
db01:6379> persist key5
(integer) 1
db01:6379> ttl key5
(integer) -1
3.3 列表
操作命令:
LPUSH命令可向list的左邊(頭部)添加一個(gè)新元素
RPUSH命令可向list的右邊(尾部)添加一個(gè)新元素.
最后LRANGE可以從list中取出一定范圍的元素
練習(xí):
db01:6379> rpush list1 A
(integer) 1
db01:6379> rpush list1 B
(integer) 2
db01:6379> lpush list1 top1
(integer) 3
db01:6379> lrange list1 0 -1
1) "top1"
2) "A"
3) "B"
db01:6379> lrange list1 1 -1
1) "A"
2) "B"
db01:6379> lrange list1 2 -1
1) "B"
操作命令:
Pop,從list中刪除元素并同時(shí)返回刪除的值,可以在左邊或右邊操作.
練習(xí):
db01:6379> rpop list1
"B"
db01:6379> lrange list1 0 -1
1) "top1"
2) "A"
db01:6379> lpop list1
"top1"
db01:6379> lrange list1 0 -1
1) "A"
3.4 哈希
操作命令:
Hash看起來就像一個(gè)’hash’的樣子.由鍵值對組成
HMSET指令設(shè)置hash中的多個(gè)域
HGET取回單個(gè)域.
HMGET取回一系列的值
練習(xí):
db01:6379> hmset user:1000 username zhangya age 27 job it
OK
db01:6379> hget user:1000 username
"zhangya"
db01:6379> hmget user:1000 username age job
1) "zhangya"
2) "27"
3) "it"
db01:6379> hgetall user:1000
1) "username"
2) "zhangya"
3) "age"
4) "27"
5) "job"
6) "it"
db01:6379> hmset user:1000 qq 526195417
OK
db01:6379> hgetall user:1000
1) "username"
2) "zhangya"
3) "age"
4) "27"
5) "job"
6) "it"
7) "qq"
8) "526195417"
3.5 集合
操作命令:
集合是字符串的無序排列,
SADD指令把新的元素添加到set中
練習(xí):
db01:6379> sadd set1 1 2 3
(integer) 3
db01:6379> smembers set1
1) "1"
2) "2"
3) "3"
和list類型不同,set集合不允許出現(xiàn)重復(fù)的元素
db01:6379> sadd set1 1 4
(integer) 1
db01:6379> smembers set1
1) "1"
2) "2"
3) "3"
4) "4"
Srem用來刪除指定的值
db01:6379> srem set1 2 4
(integer) 2
db01:6379> smembers set1
1) "1"
2) "3"
Sdiff計(jì)算集合的差異成員
db01:6379> sadd set1 1 2 3 4
(integer) 2
db01:6379> sadd set2 1 4 5
(integer) 3
db01:6379> sdiff set1 set2
1) "2"
2) "3"
Sinter計(jì)算集合的交集
db01:6379> sinter set1 set2
1) "1"
2) "4"
Sunion計(jì)算集合并集
db01:6379> sunion set1 set2
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
第4章 Redis持久化
4.1 持久化的兩種方式介紹
RDB 持久化優(yōu)缺點(diǎn)
可以在指定的時(shí)間間隔內(nèi)生成數(shù)據(jù)集的 時(shí)間點(diǎn)快照(point-in-time snapshot)。
優(yōu)點(diǎn):速度快氛悬,適合于用做備份则剃,主從復(fù)制也是基于RDB持久化功能實(shí)現(xiàn)的。
缺點(diǎn):會(huì)有數(shù)據(jù)丟失
rdb持久化核心配置參數(shù):
vim /data/6379/redis.conf
dir /data/6379
dbfilename dump.rdb
save 900 1 #900秒(15分鐘)內(nèi)有1個(gè)更改
save 300 10 #300秒(5分鐘)內(nèi)有10個(gè)更改
save 60 10000 #60秒內(nèi)有10000個(gè)更改
AOF 持久化(append-only log file)優(yōu)缺點(diǎn)
記錄服務(wù)器執(zhí)行的所有寫操作命令如捅,并在服務(wù)器啟動(dòng)時(shí)棍现,通過重新執(zhí)行這些命令來還原數(shù)據(jù)集。
AOF 文件中的命令全部以 Redis 協(xié)議的格式來保存镜遣,新命令會(huì)被追加到文件的末尾己肮。
優(yōu)點(diǎn):可以最大程度保證數(shù)據(jù)不丟
缺點(diǎn):日志記錄量級(jí)比較大
AOF持久化配置
appendonly yes #是否打開aof日志功能
appendfsync always #每1個(gè)命令,都立即同步到aof
appendfsync everysec #每秒寫1次
appendfsync no #寫入工作交給操作系統(tǒng),由操作系統(tǒng)判斷緩沖區(qū)大小,統(tǒng)一寫入到aof.
4.2 面試題
redis 持久化方式有哪些?有什么區(qū)別悲关?
rdb:基于快照的持久化谎僻,速度更快,一般用作備份寓辱,主從復(fù)制也是依賴于rdb持久化功能
aof:以追加的方式記錄redis操作日志的文件艘绍。可以最大程度的保證redis數(shù)據(jù)安全秫筏,類似于mysql的binlog
第5章 Redis安全認(rèn)證
redis默認(rèn)開啟了保護(hù)模式诱鞠,只允許本地回環(huán)地址登錄并訪問數(shù)據(jù)庫。
禁止protected-mode
protected-mode yes/no (保護(hù)模式这敬,是否只允許本地訪問)
(1)Bind :指定IP進(jìn)行監(jiān)聽
[root@db01 ~]# vim /opt/redis_cluster/redis_6379/conf/redis_6379.conf
bind 10.0.0.51 127.0.0.1
(2)增加requirepass {password}
[root@db01 ~]# vim /opt/redis_cluster/redis_6379/conf/redis_6379.conf
requirepass 123456
驗(yàn)證方法一:
[root@db01 ~]# redis-cli -a 123456
127.0.0.1:6379> set k1 v1
OK
驗(yàn)證方法二:
[root@db01 ~]# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> set k2 v2
OK
第6章 Redis主從復(fù)制
6.1 主從復(fù)制介紹
主從復(fù)制介紹
在分布式系統(tǒng)中為了解決單點(diǎn)問題,通常會(huì)把數(shù)據(jù)復(fù)制多個(gè)副本到其他機(jī)器,滿足故障恢復(fù)和負(fù)載均衡等求.
Redis也是如此,提供了復(fù)制功能.
復(fù)制功能是高可用Redis的基礎(chǔ),后面的哨兵和集群都是在復(fù)制的基礎(chǔ)上實(shí)現(xiàn)高可用的.
6.2 配置命令
6.2.1 建立復(fù)制
每個(gè)從節(jié)點(diǎn)只能有一個(gè)主節(jié)點(diǎn),主節(jié)點(diǎn)可以有多個(gè)從節(jié)點(diǎn).
配置復(fù)制的方式有三種:
1.在配置文件中加入slaveof {masterHost} {masterPort} 隨redis啟動(dòng)生效.
2.在redis-server啟動(dòng)命令后加入—slaveof {masterHost} {masterPort}生效.
3.直接使用命令:slaveof {masterHost} {masterPort}生效.
查看復(fù)制狀態(tài)信息命令
Info replication
6.2.2 斷開復(fù)制
Slaveof命令不但可以建立復(fù)制,還可以在從節(jié)點(diǎn)執(zhí)行slave of no one來斷開與主節(jié)點(diǎn)復(fù)制關(guān)系.
斷開復(fù)制主要流程:
1.斷開與主節(jié)點(diǎn)復(fù)制關(guān)系
2.從節(jié)點(diǎn)晉升為主節(jié)點(diǎn)
從節(jié)點(diǎn)斷開復(fù)制后不會(huì)拋棄原有數(shù)據(jù),只是無法再獲取主節(jié)點(diǎn)上的數(shù)據(jù)變化.
通過slaveof命令還可以實(shí)現(xiàn)切主操作,所謂切主是指把當(dāng)前從節(jié)點(diǎn)對主節(jié)點(diǎn)的復(fù)制切換到另一個(gè)主節(jié)點(diǎn).
執(zhí)行slaveof {newMasterIp} {newMasterPort}命令即可.
切主操作流程如下:
1.斷開與舊主節(jié)點(diǎn)的復(fù)制關(guān)系
2.與新主節(jié)點(diǎn)建立復(fù)制關(guān)系
3.刪除從節(jié)點(diǎn)當(dāng)前所有數(shù)據(jù)
4.對新主節(jié)點(diǎn)進(jìn)行復(fù)制操作
提示: 線上操作一定要小心,因?yàn)榍兄骱髸?huì)清空之前所有的數(shù)據(jù).
第7章 Redis Sentinel(哨兵)
7.1 哨兵介紹
Sentinel介紹
Redis的主從模式下航夺,主節(jié)點(diǎn)一旦發(fā)生故障不能提供服務(wù),需要人工干預(yù)崔涂,將從節(jié)點(diǎn)晉升為主節(jié)點(diǎn)阳掐,同時(shí)還需要修改客戶端配置。對于很多應(yīng)用場景這種方式無法接受。
Sentinel(哨兵)架構(gòu)解決了redis主從人工干預(yù)的問題锚烦。
Redis Sentinel是redis的高可用實(shí)現(xiàn)方案觅闽,實(shí)際生產(chǎn)環(huán)境中,對提高整個(gè)系統(tǒng)可用性非常有幫助的涮俄。
7.2 哨兵主要功能
Redis Sentinel 是一個(gè)分布式系統(tǒng)蛉拙, Redis Sentinel為Redis提供高可用性〕骨祝可以在沒有人為干預(yù)的情況下阻止某種類型的故障孕锄。
Redis 的 Sentinel 系統(tǒng)用于管理多個(gè) Redis 服務(wù)器(instance)該系統(tǒng)執(zhí)行以下三個(gè)任務(wù):
1.監(jiān)控(Monitoring):
Sentinel 會(huì)不斷地定期檢查你的主服務(wù)器和從服務(wù)器是否運(yùn)作正常。
2.提醒(Notification):
當(dāng)被監(jiān)控的某個(gè) Redis 服務(wù)器出現(xiàn)問題時(shí)苞尝, Sentinel 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知畸肆。
3.自動(dòng)故障遷移(Automatic failover):
當(dāng)一個(gè)主服務(wù)器不能正常工作時(shí), Sentinel 會(huì)開始一次自動(dòng)故障遷移操作宙址, 它會(huì)將失效主服務(wù)器的其中一個(gè)從服務(wù)器升級(jí)為新的主服務(wù)器轴脐, 并讓失效主服務(wù)器的其他從服務(wù)器改為復(fù)制新的主服務(wù)器; 當(dāng)客戶端試圖連接失效的主服務(wù)器時(shí)抡砂, 集群也會(huì)向客戶端返回新主服務(wù)器的地址大咱, 使得集群可以使用新主服務(wù)器代替失效服務(wù)器
架構(gòu)圖:
7.3 目錄規(guī)劃
角色 IP 端口
Master 10.0.0.51 6379
Sentinel-01 26379
Master 10.0.0.52 6379
Sentinel-01 26379
Master 10.0.0.53 6379
Sentinel-01 26379
7.4 安裝配置命令
哨兵是基于主從復(fù)制,所以需要先部署好主從復(fù)制
手工操作步驟如下:
1.先配置和創(chuàng)建好1臺(tái)服務(wù)器的節(jié)點(diǎn)和哨兵
2.使用rsync傳輸?shù)搅硗?臺(tái)機(jī)器
3.修改另外兩臺(tái)機(jī)器的IP地址
建議使用ansible劇本批量部署
7.4.1 db01命令
mkdir -p /data/redis_cluster/redis_26379
mkdir -p /opt/redis_cluster/redis_26379/{conf,pid,logs}
vim /opt/redis_cluster/redis_26379/conf/redis_26379.conf
bind 10.0.0.51
port 26379
daemonize yes
logfile /opt/redis_cluster/redis_26379/logs/redis_26379.log
dir /data/redis_cluster/redis_26379
sentinel monitor mymaster 10.0.0.51 6379 2
sentinel down-after-milliseconds mymaster 3000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 18000
7.4.2 配置文件解釋
sentinel monitor mymaster 10.0.0.51 6379 2
#mymaster主節(jié)點(diǎn)別名 主節(jié)點(diǎn) ip 和端口注益,判斷主節(jié)點(diǎn)失敗碴巾,兩個(gè) sentinel 節(jié)點(diǎn)同意
sentinel down-after-milliseconds mymaster 30000
#選項(xiàng)指定了 Sentinel 認(rèn)為服務(wù)器已經(jīng)斷線所需的毫秒數(shù)。
sentinel parallel-syncs mymaster 1
#向新的主節(jié)點(diǎn)發(fā)起復(fù)制操作的從節(jié)點(diǎn)個(gè)數(shù)丑搔,1輪詢發(fā)起復(fù)制
sentinel failover-timeout mymaster 180000
#故障轉(zhuǎn)移超時(shí)時(shí)間
7.4.3 db02/db03命令
db01
rsync -avz /opt/* db02:/opt/
rsync -avz /opt/* db03:/opt/
db02
mkdir -p /data/redis_cluster/redis_26379
cd /opt/redis_cluster/redis
make install
sed -i 's#bind 10.0.0.51#bind 10.0.0.52#g' /opt/redis_cluster/redis_6379/conf/redis_6379.conf
sed -i 's#bind 10.0.0.51#bind 10.0.0.52#g' /opt/redis_cluster/redis_26379/conf/redis_26379.conf
db03
mkdir -p /data/redis_cluster/redis_26379
cd /opt/redis_cluster/redis
make install
sed -i 's#bind 10.0.0.51#bind 10.0.0.53#g' /opt/redis_cluster/redis_6379/conf/redis_6379.conf
sed -i 's#bind 10.0.0.51#bind 10.0.0.53#g' /opt/redis_cluster/redis_26379/conf/redis_26379.conf
7.4.4 配置主從關(guān)系
db02和db03
redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf
redis-cli slaveof 10.0.0.51 6379
ps -ef|grep redis
7.4.5 啟動(dòng)哨兵
3臺(tái)都操作
redis-sentinel /opt/redis_cluster/redis_26379/conf/redis_26379.conf
7.5 配置文件的變化
當(dāng)所有節(jié)點(diǎn)啟動(dòng)后,配置文件的內(nèi)容發(fā)生了變化,體現(xiàn)在三個(gè)方面:
1)Sentinel節(jié)點(diǎn)自動(dòng)發(fā)現(xiàn)了從節(jié)點(diǎn),其余Sentinel節(jié)點(diǎn)
2)去掉了默認(rèn)配置,例如parallel-syncs failover-timeout參數(shù)
3)添加了配置紀(jì)元相關(guān)參數(shù)
查看配置文件命令
[root@db01 ~]# tail -6 /opt/redis_cluster/redis_26379/conf/redis_26379.conf
# Generated by CONFIG REWRITE
sentinel known-slave mymaster 10.0.0.52 6379
sentinel known-slave mymaster 10.0.0.53 6379
sentinel known-sentinel mymaster 10.0.0.53 26379 7794fbbb9dfb62f4d2d7f06ddef06bacb62e4c97
sentinel known-sentinel mymaster 10.0.0.52 26379 17bfab23bc53a531571790b9b31558dddeaeca40
sentinel current-epoch 0
7.6 哨兵常用操作API
登陸命令
[root@db01 ~]# redis-cli -h db01 -p 26379
Sentinel節(jié)點(diǎn)是一個(gè)特殊的Redis節(jié)點(diǎn),他們有自己專屬的API
Info Sentinel
Sentinel masters
Sentinel master <master name>
Sentinel slaves <master name>
Sentinel sentinels <master name>
Sentinel get-master-addr-by-name <master name>
Sentinel failover <master name>
Sentinel flushconfig
7.7 模擬故障轉(zhuǎn)移
停掉其中1個(gè)節(jié)點(diǎn)厦瓢,然后觀察其他節(jié)點(diǎn)的日志變化
故障轉(zhuǎn)移后配置文件變化
Redis Sentinel存在多個(gè)從節(jié)點(diǎn)時(shí),如果想將指定的從節(jié)點(diǎn)晉升為主節(jié)點(diǎn),可以將其他從節(jié)點(diǎn)的slavepriority配置為0,但是需要注意failover后,將slave-priority調(diào)回原值.
1.查詢命令:CONFIG GET slave-priority
2.設(shè)置命令:CONFIG SET slave-priority 0
3.主動(dòng)切換:sentinel failover mymaster
操作過程:
db02/db03操作
redis-cli -h db02 -p 6379 CONFIG SET slave-priority 0
redis-cli -h db03 -p 6379 CONFIG SET slave-priority 0
db01操作
redis-cli -h db01 -p 26379 Sentinel failover mymaster
第8章 Redis Cluster
8.1 集群介紹
Redis Cluster 是 redis的分布式解決方案,在3.0版本正式推出
當(dāng)遇到單機(jī)啤月、內(nèi)存煮仇、并發(fā)、流量等瓶頸時(shí)顽冶,可以采用Cluster架構(gòu)方案達(dá)到負(fù)載均衡目的欺抗。
Redis Cluster之前的分布式方案有兩種:
1)客戶端分區(qū)方案,優(yōu)點(diǎn)分區(qū)邏輯可控强重,缺點(diǎn)是需要自己處理數(shù)據(jù)路由绞呈,高可用和故障轉(zhuǎn)移等。
- 代理方案间景,優(yōu)點(diǎn)是簡化客戶端分布式邏輯和升級(jí)維護(hù)便利佃声,缺點(diǎn)加重架構(gòu)部署和性能消耗。
官方提供的 Redis Cluster集群方案倘要,很好的解決了集群方面的問題
8.2 數(shù)據(jù)分布
分布式數(shù)據(jù)庫首先要解決把整個(gè)數(shù)據(jù)庫集按照分區(qū)規(guī)則映射到多個(gè)節(jié)點(diǎn)的問題圾亏,即把數(shù)據(jù)集劃分到多個(gè)節(jié)點(diǎn)上十拣,每個(gè)節(jié)點(diǎn)負(fù)責(zé)整體數(shù)據(jù)的一個(gè)子集,需要關(guān)注的是數(shù)據(jù)分片規(guī)則志鹃,Redis Cluster采用哈希分片規(guī)則夭问。
8.3 目錄規(guī)劃
# redis安裝目錄
/opt/redis_cluster/redis_{PORT}/{conf,logs,pid}
# redis數(shù)據(jù)目錄
/data/redis_cluster/redis_{PORT}/redis_{PORT}.rdb
# redis運(yùn)維腳本
/root/scripts/redis_shell.sh
8.4 集群拓?fù)?/h2>
不太合理的拓?fù)洌?/p>
合理的拓?fù)洌?/p>
8.5 手動(dòng)搭建部署集群
思路:
1)部署一臺(tái)服務(wù)器上的2個(gè)集群節(jié)點(diǎn)
2)發(fā)送完成后修改其他主機(jī)的IP地址
3)使用ansible批量部署
實(shí)現(xiàn)命令:
db01操作
mkdir -p /opt/redis_cluster/redis_{6380,6381}/{conf,logs,pid}
mkdir –p /data/redis_cluster/redis_{6380,6381}
cat >/opt/redis_cluster/redis_6380/conf/redis_6380.conf<<EOF
bind 10.0.0.51
port 6380
daemonize yes
pidfile "/opt/redis_cluster/redis_6380/pid/redis_6380.pid"
logfile "/opt/redis_cluster/redis_6380/logs/redis_6380.log"
dbfilename "redis_6380.rdb"
dir "/data/redis_cluster/redis_6380/"
cluster-enabled yes
cluster-config-file nodes_6380.conf
cluster-node-timeout 15000
EOF
cd /opt/redis_cluster/
cp redis_6380/conf/redis_6380.conf redis_6381/conf/redis_6381.conf
sed -i 's#6380#6381#g' redis_6381/conf/redis_6381.conf
rsync -avz /opt/redis_cluster/redis_638* db02:/opt/redis_cluster/
rsync -avz /opt/redis_cluster/redis_638* db03:/opt/redis_cluster/
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf
db02操作:
find /opt/redis_cluster/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#51#52#g"
mkdir –p /data/redis_cluster/redis_{6380,6381}
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf
db03操作
find /opt/redis_cluster/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#51#53#g"
mkdir –p /data/redis_cluster/redis_{6380,6381}
redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf
8.5.1 手動(dòng)配置節(jié)點(diǎn)發(fā)現(xiàn)
當(dāng)把所有節(jié)點(diǎn)都啟動(dòng)后查看進(jìn)程會(huì)有cluster的字樣
但是登錄后執(zhí)行CLUSTER NODES命令會(huì)發(fā)現(xiàn)只有每個(gè)節(jié)點(diǎn)自己的ID,目前集群內(nèi)的節(jié)點(diǎn)
還沒有互相發(fā)現(xiàn),所以搭建redis集群我們第一步要做的就是讓集群內(nèi)的節(jié)點(diǎn)互相發(fā)現(xiàn).
在執(zhí)行節(jié)點(diǎn)發(fā)現(xiàn)命令之前我們先查看一下集群的數(shù)據(jù)目錄會(huì)發(fā)現(xiàn)有生成集群的配置文件
查看后發(fā)現(xiàn)只有自己的節(jié)點(diǎn)內(nèi)容,等節(jié)點(diǎn)全部發(fā)現(xiàn)后會(huì)把所發(fā)現(xiàn)的節(jié)點(diǎn)ID寫入這個(gè)文件
集群模式的Redis除了原有的配置文件之外又加了一份集群配置文件.當(dāng)集群內(nèi)節(jié)點(diǎn)
信息發(fā)生變化,如添加節(jié)點(diǎn),節(jié)點(diǎn)下線,故障轉(zhuǎn)移等.節(jié)點(diǎn)會(huì)自動(dòng)保存集群狀態(tài)到配置文件.
需要注意的是,Redis自動(dòng)維護(hù)集群配置文件,不需要手動(dòng)修改,防止節(jié)點(diǎn)重啟時(shí)產(chǎn)生錯(cuò)亂.
節(jié)點(diǎn)發(fā)現(xiàn)使用命令: CLUSTER MEET {IP} {PORT}
提示:在集群內(nèi)任意一臺(tái)機(jī)器執(zhí)行此命令就可以
[root@db01 ~]# sh redis_shell.sh login 6380
10.0.0.51:6380> CLUSTER MEET 10.0.0.51 6381
OK
10.0.0.51:6380> CLUSTER MEET 10.0.0.52 6380
OK
10.0.0.51:6380> CLUSTER MEET 10.0.0.53 6380
OK
10.0.0.51:6380> CLUSTER MEET 10.0.0.52 6381
OK
10.0.0.51:6380> CLUSTER MEET 10.0.0.53 6381
OK
10.0.0.51:6380> CLUSTER NODES
d03cb38d612802aead8f727b1726a3359c241818 10.0.0.51:6380 myself,master - 0 0 4 connected
67c8128df00b2fa304a41bafbadac25a654f196d 10.0.0.51:6381 master - 0 1562059947079 1 connected
a23ec7d444791a0b258ac454ef15cb4d6ab5abd2 10.0.0.53:6381 master - 0 1562059948087 5 connected
e57807d4d35daaaca05f4a9705e844eab15c7ce8 10.0.0.52:6381 master - 0 1562059949098 0 connected
aa9da67a594dfb357195f12ca4c44001804ee470 10.0.0.53:6380 master - 0 1562059945063 3 connected
5cb6895305520e6a0aa4198a6ea5f2c087530b41 10.0.0.52:6380 master - 0 1562059950108 2 connected
節(jié)點(diǎn)都發(fā)現(xiàn)完畢后我們再次查看集群配置文件
可以看到,發(fā)現(xiàn)到的節(jié)點(diǎn)的ID也被寫入到了集群的配置文件里
8.5.2 Redis Cluster 通訊流程
在分布式存儲(chǔ)中需要提供維護(hù)節(jié)點(diǎn)元數(shù)據(jù)信息的機(jī)制,所謂元數(shù)據(jù)是指:節(jié)點(diǎn)負(fù)責(zé)哪些數(shù)據(jù)曹铃,是否出現(xiàn)故障燈狀態(tài)信息缰趋,redis 集群采用 Gossip(流言)協(xié)議,Gossip 協(xié)議工作原理就是節(jié)點(diǎn)彼此不斷交換信息陕见,一段時(shí)間后所有的節(jié)點(diǎn)都會(huì)知道集群完整信息秘血,這種方式類似流言傳播。
通信過程:
1)集群中的每一個(gè)節(jié)點(diǎn)都會(huì)單獨(dú)開辟一個(gè) Tcp 通道评甜,用于節(jié)點(diǎn)之間彼此通信灰粮,通信端口在基礎(chǔ)端口上家10000.
2)每個(gè)節(jié)點(diǎn)在固定周期內(nèi)通過特定規(guī)則選擇結(jié)構(gòu)節(jié)點(diǎn)發(fā)送 ping 消息
3)接收到 ping 消息的節(jié)點(diǎn)用 pong 消息作為響應(yīng)。集群中每個(gè)節(jié)點(diǎn)通過一定規(guī)則挑選要通信的節(jié)點(diǎn)忍坷,每個(gè)節(jié)點(diǎn)可能知道全部節(jié)點(diǎn)粘舟,也可能僅知道部分節(jié)點(diǎn),只要這些節(jié)點(diǎn)彼此可以正常通信承匣,最終他們會(huì)打成一致的狀態(tài)蓖乘,當(dāng)節(jié)點(diǎn)出現(xiàn)故障,新節(jié)點(diǎn)加入韧骗,主從角色變化等,它能夠給不斷的ping/pong消息零聚,從而達(dá)到同步目的袍暴。
通訊消息類型:
Gossip
Gossip 協(xié)議職責(zé)就是信息交換,信息交換的載體就是節(jié)點(diǎn)間彼此發(fā)送Gossip 消息隶症。
常見 Gossip 消息分為:ping政模、 pong、 meet蚂会、 fail 等
meet
meet 消息:用于通知新節(jié)點(diǎn)加入淋样,消息發(fā)送者通知接受者加入到當(dāng)前集群,meet 消息通信正常完成后胁住,接收節(jié)點(diǎn)會(huì)加入到集群中并進(jìn)行ping趁猴、 pong 消息交換
ping
ping 消息:集群內(nèi)交換最頻繁的消息,集群內(nèi)每個(gè)節(jié)點(diǎn)每秒想多個(gè)其他節(jié)點(diǎn)發(fā)送 ping 消息彪见,用于檢測節(jié)點(diǎn)是否在線和交換彼此信息儡司。
pong
Pong 消息:當(dāng)接收到 ping,meet 消息時(shí)余指,作為相應(yīng)消息回復(fù)給發(fā)送方確認(rèn)消息正常通信捕犬,節(jié)點(diǎn)也可以向集群內(nèi)廣播自身的 pong 消息來通知整個(gè)集群對自身狀態(tài)進(jìn)行更新。
fail
fail 消息:當(dāng)節(jié)點(diǎn)判定集群內(nèi)另一個(gè)節(jié)點(diǎn)下線時(shí),回向集群內(nèi)廣播一個(gè)fail 消息碉碉,其他節(jié)點(diǎn)收到 fail 消息之后把對應(yīng)節(jié)點(diǎn)更新為下線狀態(tài)柴钻。
通訊示意圖:
8.5.3 Redis Cluster手動(dòng)分配槽位
雖然節(jié)點(diǎn)之間已經(jīng)互相發(fā)現(xiàn)了,但是此時(shí)集群還是不可用的狀態(tài),因?yàn)椴]有給節(jié)點(diǎn)分配槽位,而且必須是所有的槽位都分配完畢后整個(gè)集群才是可用的狀態(tài).
反之,也就是說只要有一個(gè)槽位沒有分配,那么整個(gè)集群就是不可用的.
測試命令:
[root@db01 ~]# sh redis_shell.sh login 6380
10.0.0.51:6380> set k1 v1
(error) CLUSTERDOWN Hash slot not served
10.0.0.51:6380> CLUSTER INFO
cluster_state:fail
cluster_slots_assigned:0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:0
cluster_current_epoch:5
cluster_my_epoch:4
cluster_stats_messages_sent:1200
cluster_stats_messages_received:1200
10.0.0.51:6380>
前面說了,我們雖然有6個(gè)節(jié)點(diǎn),但是真正負(fù)責(zé)數(shù)據(jù)寫入的只有3個(gè)節(jié)點(diǎn),其他3個(gè)節(jié)點(diǎn)只是作為主節(jié)點(diǎn)的從節(jié)點(diǎn),也就是說,只需要分配期中三個(gè)節(jié)點(diǎn)的槽位就可以了
分配槽位的方法:
分配槽位需要在每個(gè)主節(jié)點(diǎn)上來配置,此時(shí)有2種方法執(zhí)行:
1.分別登錄到每個(gè)主節(jié)點(diǎn)的客戶端來執(zhí)行命令
2.在其中一臺(tái)機(jī)器上用redis客戶端遠(yuǎn)程登錄到其他機(jī)器的主節(jié)點(diǎn)上執(zhí)行命令
每個(gè)節(jié)點(diǎn)執(zhí)行命令:
[root@db01 ~]# redis-cli -h db01 -p 6380 cluster addslots {0..5461}
OK
[root@db01 ~]# redis-cli -h db02 -p 6380 cluster addslots {5462..10922}
OK
[root@db01 ~]# redis-cli -h db03 -p 6380 cluster addslots {10923..16383}
OK
分配完所有槽位之后我們再查看一下集群的節(jié)點(diǎn)狀態(tài)和集群狀態(tài)
可以看到三個(gè)節(jié)點(diǎn)都分配了槽位,而且集群的狀態(tài)是OK的
8.5.4 手動(dòng)配置集群高可用
雖然這時(shí)候集群是可用的了,但是整個(gè)集群只要有一臺(tái)機(jī)器壞掉了,那么整個(gè)集群都是不可用的.
所以這時(shí)候需要用到其他三個(gè)節(jié)點(diǎn)分別作為現(xiàn)在三個(gè)主節(jié)點(diǎn)的從節(jié)點(diǎn),以應(yīng)對集群主節(jié)點(diǎn)故障時(shí)可以進(jìn)行自動(dòng)切換以保證集群持續(xù)可用.
注意:
1.不要讓復(fù)制節(jié)點(diǎn)復(fù)制本機(jī)器的主節(jié)點(diǎn), 因?yàn)槿绻菢拥脑挋C(jī)器掛了集群還是不可用狀態(tài), 所以復(fù)制節(jié)點(diǎn)要復(fù)制其他服務(wù)器的主節(jié)點(diǎn).
2.使用redis-trid工具自動(dòng)分配的時(shí)候會(huì)出現(xiàn)復(fù)制節(jié)點(diǎn)和主節(jié)點(diǎn)在同一臺(tái)機(jī)器上的情況,需要注意
8.5.5 測試集群
這一次我們采用在一臺(tái)機(jī)器上使用redis客戶端遠(yuǎn)程操作集群其他節(jié)點(diǎn)
注意:
1.需要執(zhí)行命令的是每個(gè)服務(wù)器的從節(jié)點(diǎn)
2.注意主從的ID不要搞混了.
執(zhí)行命令:
[root@db01 ~]# redis-cli -h db01 -p 6381 CLUSTER REPLICATE 5cb6895305520e6a0aa4198a6ea5f2c087530b41
OK
[root@db01 ~]# redis-cli -h db02 -p 6381 CLUSTER REPLICATE aa9da67a594dfb357195f12ca4c44001804ee470
OK
[root@db01 ~]# redis-cli -h db03 -p 6381 CLUSTER REPLICATE d03cb38d612802aead8f727b1726a3359c241818
OK
8.6 Redis Cluster測試集群
我們使用常規(guī)插入redis數(shù)據(jù)的方式往集群里寫入數(shù)據(jù)看看會(huì)發(fā)生什么
[root@db01 ~]# redis-cli -h db01 -p 6380 set k1 v1
(error) MOVED 12706 10.0.0.53:6380
結(jié)果提示error, 但是給出了集群另一個(gè)節(jié)點(diǎn)的地址
那么這條數(shù)據(jù)到底有沒有寫入呢? 我們登錄這兩個(gè)節(jié)點(diǎn)分別查看
[root@db01 ~]# redis-cli -h db03 -p 6380 get k1
(nil)
結(jié)果沒有,這是因?yàn)槭褂眉汉笥捎跀?shù)據(jù)被分片了,所以并不是說在那臺(tái)機(jī)器上寫入數(shù)據(jù)就會(huì)在哪臺(tái)機(jī)器的節(jié)點(diǎn)上寫入,集群的數(shù)據(jù)寫入和讀取就涉及到了另外一個(gè)概念,ASK路由
8.7 Redis Cluster ASK路由介紹
在集群模式下,Redis接受任何鍵相關(guān)命令時(shí)首先會(huì)計(jì)算鍵對應(yīng)的槽,再根據(jù)槽找出所對應(yīng)的節(jié)點(diǎn)
如果節(jié)點(diǎn)是自身,則處理鍵命令;
否則回復(fù)MOVED重定向錯(cuò)誤,通知客戶端請求正確的節(jié)點(diǎn),這個(gè)過程稱為Mover重定向.
知道了ask路由后,我們使用-c選項(xiàng)批量插入一些數(shù)據(jù)
[root@db01 ~]# cat input_key.sh
#!/bin/bash
for i in $(seq 1 1000)
do
redis-cli -c -h db01 -p 6380 set k_${i} v_${i} && echo "set k_${i} is ok"
done
寫入后我們同樣使用-c選項(xiàng)來讀取剛才插入的鍵值,然后查看下redis會(huì)不會(huì)幫我們路由到正確的節(jié)點(diǎn)上
[root@db01 ~]# redis-cli -c -h db01 -p 6380
db01:6380> get k_1
"v_1"
db01:6380> get k_100
-> Redirected to slot [5541] located at 10.0.0.52:6380
"v_100"
10.0.0.52:6380> get k_1000
-> Redirected to slot [79] located at 10.0.0.51:6380
"v_1000"
10.0.0.51:6380>
8.8 模擬故障轉(zhuǎn)移
至此,我們已經(jīng)手動(dòng)的把一個(gè)redis高可用的集群部署完畢了, 但是還沒有模擬過故障
這里我們就模擬故障,停掉期中一臺(tái)主機(jī)的redis節(jié)點(diǎn),然后查看一下集群的變化
我們使用暴力的kill -9殺掉 db02上的redis集群節(jié)點(diǎn),然后觀察節(jié)點(diǎn)狀態(tài)
理想情況應(yīng)該是db01上的6381從節(jié)點(diǎn)升級(jí)為主節(jié)點(diǎn)
在db01上查看集群節(jié)點(diǎn)狀態(tài)
雖然我們已經(jīng)測試了故障切換的功能,但是節(jié)點(diǎn)修復(fù)后還是需要重新上線
所以這里測試節(jié)點(diǎn)重新上線后的操作
重新啟動(dòng)db02的6380,然后觀察日志
觀察db01上的日志
這時(shí)假如我們想讓修復(fù)后的節(jié)點(diǎn)重新上線,可以在想變成主庫的從庫執(zhí)行CLUSTER FAILOVER命令
這里我們在db02的6380上執(zhí)行
8.9 使用工具搭建部署Redis Cluster
手動(dòng)搭建集群便于理解集群創(chuàng)建的流程和細(xì)節(jié),不過手動(dòng)搭建集群需要很多步驟垢粮,當(dāng)集群節(jié)點(diǎn)眾多時(shí)贴届,必然會(huì)加大搭建集群的復(fù)雜度和運(yùn)維成本,因此官方提供了 redis-trib.rb的工具方便我們快速搭建集群足丢。
redis-trib.rb是采用 Ruby 實(shí)現(xiàn)的 redis 集群管理工具粱腻,內(nèi)部通過 Cluster相關(guān)命令幫我們簡化集群創(chuàng)建、檢查斩跌、槽遷移和均衡等常見運(yùn)維操作绍些,使用前要安裝 ruby 依賴環(huán)境
安裝命令:
yum makecache fast
yum install rubygems
gem sources --remove https://rubygems.org/
gem sources -a http://mirrors.aliyun.com/rubygems/
gem update - system
gem install redis -v 3.3.5
我們可以停掉所有的節(jié)點(diǎn),然后清空數(shù)據(jù)耀鸦,恢復(fù)成一個(gè)全新的集群柬批,所有機(jī)器執(zhí)行命令
pkill redis
rm -rf /data/redis_cluster/redis_6380/*
rm -rf /data/redis_cluster/redis_6381/*
全部清空之后啟動(dòng)所有的節(jié)點(diǎn),所有機(jī)器執(zhí)行
sh redis_shell.sh start 6380
sh redis_shell.sh start 6381
db01執(zhí)行創(chuàng)建集群命令
cd /opt/redis_cluster/redis/src/
./redis-trib.rb create --replicas 1 10.0.0.51:6380 10.0.0.52:6380 10.0.0.53:6380 10.0.0.51:6381 10.0.0.52:6381 10.0.0.53:6381
檢查集群完整性
./redis-trib.rb check 10.0.0.51:6380
檢查集群負(fù)載平衡
./redis-trib.rb rebalance 10.0.0.51:6380
8.10 工具擴(kuò)容節(jié)點(diǎn)
Redis集群的擴(kuò)容操作可分為以下幾個(gè)步驟
1)準(zhǔn)備新節(jié)點(diǎn)
2)加入集群
3)遷移槽和數(shù)據(jù)
擴(kuò)容流程圖:
我們在db01上創(chuàng)建2個(gè)新節(jié)點(diǎn)
mkdir -p /opt/redis_cluster/redis_{6390,6391}/{conf,logs,pid}
mkdir -p /data/redis_cluster/redis_{6390,6391}
cd /opt/redis_cluster/
cp redis_6380/conf/redis_6380.conf redis_6390/conf/redis_6390.conf
cp redis_6380/conf/redis_6380.conf redis_6391/conf/redis_6391.conf
sed -i 's#6380#6390#g' redis_6390/conf/redis_6390.conf
sed -i 's#6380#6391#g' redis_6391/conf/redis_6391.conf
啟動(dòng)節(jié)點(diǎn)
bash redis_shell.sh start 6390
bash redis_shell.sh start 6391
發(fā)現(xiàn)節(jié)點(diǎn)
redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.51 6390
redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.51 6391
在db01上使用工具擴(kuò)容
cd /opt/redis_cluster/redis/src/
./redis-trib.rb reshard 10.0.0.51:6380
打印出進(jìn)群每個(gè)節(jié)點(diǎn)信息后,reshard命令需要確認(rèn)遷移的槽數(shù)量,這里我們輸入4096個(gè):
How many slots do you want to move (from 1 to 16384)? 4096
輸入6390的節(jié)點(diǎn)ID作為目標(biāo)節(jié)點(diǎn),也就是要擴(kuò)容的節(jié)點(diǎn),目標(biāo)節(jié)點(diǎn)只能指定一個(gè)
What is the receiving node ID? xxxxxxxxx
之后輸入源節(jié)點(diǎn)的ID,這里分別輸入每個(gè)主節(jié)點(diǎn)的6380的ID最后輸入done,或者直接輸入all
Source node #1:all
遷移完成后命令會(huì)自動(dòng)退出,這時(shí)候我們查看一下集群的狀態(tài)(遷移過程數(shù)據(jù)不會(huì)丟失袖订,不會(huì)中斷)
./redis-trib.rb rebalance 10.0.0.51:6380
8.11 工具收縮節(jié)點(diǎn)
流程說明
1).首先需要確定下線節(jié)點(diǎn)是否有負(fù)責(zé)的槽,
如果是,需要把槽遷移到其他節(jié)點(diǎn),保證節(jié)點(diǎn)下線后整個(gè)集群槽節(jié)點(diǎn)映射的完整性.
2).當(dāng)下線節(jié)點(diǎn)不再負(fù)責(zé)槽或者本身是從節(jié)點(diǎn)時(shí),
就可以通知集群內(nèi)其他節(jié)點(diǎn)忘記下線節(jié)點(diǎn),當(dāng)所有的節(jié)點(diǎn)忘記該節(jié)點(diǎn)后可以正常關(guān)閉.
這里我們準(zhǔn)備將剛才新添加的節(jié)點(diǎn)下線,也就是6390和6391
收縮和擴(kuò)容遷移的方向相反,6390變?yōu)樵垂?jié)點(diǎn),其他節(jié)點(diǎn)變?yōu)槟繕?biāo)節(jié)點(diǎn),源節(jié)點(diǎn)把自己負(fù)責(zé)的4096個(gè)槽均勻的遷移到其他節(jié)點(diǎn)上,.
由于redis-trib..rb reshard命令只能有一個(gè)目標(biāo)節(jié)點(diǎn),因此需要執(zhí)行3次reshard命令,分別遷移1365,1365,1366個(gè)槽.
操作命令:
cd /opt/redis_cluster/redis/src/
./redis-trib.rb reshard 10.0.0.51:6380
How many slots do you want to move (from 1 to 16384)? 1365
輸入6380的id
輸入6390的id
done
8.12 忘記節(jié)點(diǎn)
由于我們的集群是做了高可用的,所以當(dāng)主節(jié)點(diǎn)下線的時(shí)候從節(jié)點(diǎn)也會(huì)頂上,所以最好我們先下線從節(jié)點(diǎn),然后在下線主節(jié)點(diǎn)
cd /opt/redis_cluster/redis/src/
./redis-trib.rb del-node 10.0.0.51:6391 ID
./redis-trib.rb del-node 10.0.0.51:6390 ID
第9章 Redis集群常用命令
集群(cluster)
CLUSTER INFO 打印集群的信息
CLUSTER NODES 列出集群當(dāng)前已知的所有節(jié)點(diǎn)(node)氮帐,以及這些節(jié)點(diǎn)的相關(guān)信息。
節(jié)點(diǎn)(node)
CLUSTER MEET <ip> <port> 將 ip 和 port 所指定的節(jié)點(diǎn)添加到集群當(dāng)中洛姑,讓它成為集群的一份子上沐。
CLUSTER FORGET <node_id> 從集群中移除 node_id 指定的節(jié)點(diǎn)。
CLUSTER REPLICATE <node_id> 將當(dāng)前節(jié)點(diǎn)設(shè)置為 node_id 指定的節(jié)點(diǎn)的從節(jié)點(diǎn)楞艾。
CLUSTER SAVECONFIG 將節(jié)點(diǎn)的配置文件保存到硬盤里面参咙。
槽(slot)
CLUSTER ADDSLOTS <slot> [slot ...] 將一個(gè)或多個(gè)槽(slot)指派(assign)給當(dāng)前節(jié)點(diǎn)。
CLUSTER DELSLOTS <slot> [slot ...] 移除一個(gè)或多個(gè)槽對當(dāng)前節(jié)點(diǎn)的指派硫眯。
CLUSTER FLUSHSLOTS 移除指派給當(dāng)前節(jié)點(diǎn)的所有槽蕴侧,讓當(dāng)前節(jié)點(diǎn)變成一個(gè)沒有指派任何槽的節(jié)點(diǎn)。
CLUSTER SETSLOT <slot> NODE <node_id> 將槽 slot 指派給 node_id 指定的節(jié)點(diǎn)两入,如果槽已經(jīng)指派給另一個(gè)節(jié)點(diǎn)净宵,那么先讓另一個(gè)節(jié)點(diǎn)刪除該槽>,然后再進(jìn)行指派裹纳。
CLUSTER SETSLOT <slot> MIGRATING <node_id> 將本節(jié)點(diǎn)的槽 slot 遷移到 node_id 指定的節(jié)點(diǎn)中择葡。
CLUSTER SETSLOT <slot> IMPORTING <node_id> 從 node_id 指定的節(jié)點(diǎn)中導(dǎo)入槽 slot 到本節(jié)點(diǎn)。
CLUSTER SETSLOT <slot> STABLE 取消對槽 slot 的導(dǎo)入(import)或者遷移(migrate)痊夭。
鍵 (key)
CLUSTER KEYSLOT <key> 計(jì)算鍵 key 應(yīng)該被放置在哪個(gè)槽上刁岸。
CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的鍵值對數(shù)量。CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 個(gè) slot 槽中的鍵她我。
第10章 Redis運(yùn)維工具
10.1 運(yùn)維腳本
[root@db01 ~]# cat redis_shell.sh
#!/bin/bash
USAG(){
echo "sh $0 {start|stop|restart|login|ps|tail} PORT"
}
if [ "$#" = 1 ]
then
REDIS_PORT='6379'
elif
[ "$#" = 2 -a -z "$(echo "$2"|sed 's#[0-9]##g')" ]
then
REDIS_PORT="$2"
else
USAG
exit 0
fi
REDIS_IP=$(hostname -I|awk '{print $1}')
PATH_DIR=/opt/redis_cluster/redis_${REDIS_PORT}/
PATH_CONF=/opt/redis_cluster/redis_${REDIS_PORT}/conf/redis_${REDIS_PORT}.conf
PATH_LOG=/opt/redis_cluster/redis_${REDIS_PORT}/logs/redis_${REDIS_PORT}.log
CMD_START(){
redis-server ${PATH_CONF}
}
CMD_SHUTDOWN(){
redis-cli -c -h ${REDIS_IP} -p ${REDIS_PORT} shutdown
}
CMD_LOGIN(){
redis-cli -c -h ${REDIS_IP} -p ${REDIS_PORT}
}
CMD_PS(){
ps -ef|grep redis
}
CMD_TAIL(){
tail -f ${PATH_LOG}
}
case $1 in
start)
CMD_START
CMD_PS
;;
stop)
CMD_SHUTDOWN
CMD_PS
;;
restart)
CMD_START
CMD_SHUTDOWN
CMD_PS
;;
login)
CMD_LOGIN
;;
ps)
CMD_PS
;;
tail)
CMD_TAIL
;;
*)
USAG
esac
10.2 數(shù)據(jù)導(dǎo)入導(dǎo)出工具
需求背景
剛切換到redis集群的時(shí)候肯定會(huì)面臨數(shù)據(jù)導(dǎo)入的問題,所以這里推薦使用redis-migrate-tool工具來導(dǎo)入單節(jié)點(diǎn)數(shù)據(jù)到集群里
官方地址:
http://www.oschina.net/p/redis-migrate-tool
安裝工具
cd /opt/redis_cluster/
git clone https://github.com/vipshop/redis-migrate-tool.git
cd redis-migrate-tool/
autoreconf -fvi
./configure
make && make install
創(chuàng)建配置文件
[root@db01 ~]# cat > redis_6379_to_6380.conf << eof
[source]
type: single
servers:
- 10.0.0.51:6379
[target]
type: redis cluster
servers:
- 10.0.0.51:6380
[common]
listen: 0.0.0.0:8888
source_safe: true
生成測試數(shù)據(jù)
[root@db01 ~]# cat input_key.sh
#!/bin/bash
for i in $(seq 1 1000)
do
redis-cli -c -h db01 -p 6379 set k_${i} v_${i} && echo "set k_${i} is ok"
done
執(zhí)行導(dǎo)入命令
[root@db01 ~]# redis-migrate-tool -c redis_6379_to_6380.conf
數(shù)據(jù)校驗(yàn)
[root@db01 ~]# redis-migrate-tool -c redis_6379_to_6380.conf -C redis_check
10.3 分析鍵值大小
需求背景
redis的內(nèi)存使用太大鍵值太多,不知道哪些鍵值占用的容量比較大,而且在線分析會(huì)影響性能.
安裝工具
yum install python-pip gcc python-devel
cd /opt/
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
python setup.py install
使用方法
cd /data/redis_cluster/redis_6380/
rdb -c memory redis_6380.rdb -f redis_6380.rdb.csv
分析rdb并導(dǎo)出
awk -F ',' '{print $4,$2,$3,$1}' redis_6380.rdb.csv |sort > 6380.txt
10.4 監(jiān)控過期鍵
需求背景
因?yàn)殚_發(fā)重復(fù)提交虹曙,導(dǎo)致電商網(wǎng)站優(yōu)惠卷過期時(shí)間失效
問題分析
如果一個(gè)鍵已經(jīng)設(shè)置了過期時(shí)間迫横,這時(shí)候在set這個(gè)鍵,過期時(shí)間就會(huì)取消
解決思路
如何在不影響機(jī)器性能的前提下批量獲取需要監(jiān)控鍵過期時(shí)間
1.Keys * 查出來匹配的鍵名酝碳。然后循環(huán)讀取ttl時(shí)間
2.scan * 范圍查詢鍵名矾踱。然后循環(huán)讀取ttl時(shí)間
Keys 重操作,會(huì)影響服務(wù)器性能疏哗,除非是不提供服務(wù)的從節(jié)點(diǎn)
Scan 負(fù)擔(dān)小呛讲,但是需要去多次才能取完,需要寫腳本
腳本內(nèi)容:
cat 01get_key.sh
#!/bin/bash
key_num=0
> key_name.log
for line in $(cat key_list.txt)
do
while true
do
scan_num=$(redis-cli -h 192.168.47.75 -p 6380 SCAN ${key_num} match ${line}\* count 1000|awk 'NR==1{print $0}')
key_name=$(redis-cli -h 192.168.47.75 -p 6380 SCAN ${key_num} match ${line}\* count 1000|awk 'NR>1{print $0}')
echo ${key_name}|xargs -n 1 >> key_name.log
((key_num=scan_num))
if [ ${key_num} == 0 ]
then
break
fi
done
done