官方文檔:
https://redis.io/topics/persistencenode
1.RDB和AOF優缺點 RDB: 能夠在指定的時間間隔內生成數據集的時間點快照,把當前內存裏的狀態快照到磁盤上 優勢: 壓縮格式/恢復速度快,適用於備份,主從複製也是基於rdb持久化功能實現 缺點: 可能會丟失數據 AOF: 相似於mysql的binlog,重寫,、每次操做都寫一次/1秒寫一次,文件中的命令所有以redis協議的格式保存,新命令會被追加到文件的末尾 優勢: 安全,有可能會丟失1秒的數據 缺點: 文件比較大,恢復速度慢 2.配置RDB #900秒內有一個更改,300秒內有10個更改,....... save 900 1 save 300 10 save 60 10000 dir /data/redis_6379/ dbfilename redis_6379.rdb 結論: 1.執行shutdown的時候,內部會自動執行bgsave,而後再執行shutdown 2.pkill kill killall 都相似於執行shutdown命令.會觸發bgsave持久化 3.恢復的時候,rdb文件名稱要和配置文件裏寫的同樣 4.若是沒有配置save參數,執行shutdown不會自動bgsave持久化 5.若是沒有配置save參數,能夠手動執行bgsave觸發持久化保存 6.kill -9 redis 不會出發持久化 經常使用命令: ll /data/redis_6379/ cat /opt/redis_6379/conf/redis_6379.conf vim /opt/redis_6379/conf/redis_6379.conf pkill redis redis-server /opt/redis_6379/conf/redis_6379.conf redis-cli -h db01 redis-cli -h db01 shutdown bash for.sh 3.配置AOF appendonly yes #是否打開aof日誌功能 appendfsync always #每1個命令,都當即同步到aof appendfsync everysec #每秒寫1次 appendfsync no #寫入工做交給操做系統,由操做系統判斷緩衝區大小,統一寫入到aof. appendfilename "redis_6379.aof" appendonly yes appendfsync everysec 實驗: 若是aof和rdb文件同時存在,redis會如何讀取: 實驗步驟: 1.插入一條數據 aof: 有記錄 rdb: 沒有記錄 2.複製到其餘地方 3.把redis停掉 4.清空數據目錄 5.把數據文件拷貝過來 aof: 有記錄 rdb: 沒有記錄 6.啓動redis 7.測試,若是有新插入的數據,就表示讀取的是aof,若是沒有,就表示讀取的是rdb 實驗結論: 若是2種數據格式都存在,優先讀取aof 如何選擇: 好的,那我該怎麼用? 一般的指示是,若是您但願得到與PostgreSQL能夠提供的功能至關的數據安全性,則應同時使用兩種持久性方法。 若是您很是關心數據,可是在災難狀況下仍然能夠承受幾分鐘的數據丟失,則能夠僅使用RDB。 有不少用戶單獨使用AOF,但咱們不建議這樣作,由於不時擁有RDB快照對於進行數據庫備份,加快重啓速度以及AOF引擎中存在錯誤是一個好主意。 注意:因爲全部這些緣由,咱們未來可能會最終將AOF和RDB統一爲一個持久性模型(長期計劃)。 如下各節將說明有關這兩個持久性模型的更多詳細信息。
redis默認開啓了保護模式,只容許本地迴環地址登陸並訪問數據庫python
禁止protected-mode
protected-mode yes/no (保護模式,是否只容許本地訪問)mysql
1.Bind :指定IP進行監聽 vim /opt/redis_cluster/redis_6379/conf/redis_6379.conf bind 10.0.0.51 127.0.0.1 #增長requirepass {password} vim /opt/redis_cluster/redis_6379/conf/redis_6379.conf requirepass 123456 2.使用密碼登陸 兩種方式: 第一種: redis-cli -h db01 AUTH 123456 第二種: redis-cli -h db01 -a 123456 get k_1 ======================================== #禁用危險命令 配置文件裏添加禁用危險命令的參數 1)禁用命令 rename-command KEYS "" rename-command FLUSHALL "" rename-command FLUSHDB "" rename-command CONFIG "" 2)重命名命令 rename-command KEYS "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" rename-command FLUSHALL "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" rename-command FLUSHDB "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" rename-command CONFIG "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
主從複製介紹
在分佈式系統中爲了解決單點問題,一般會把數據複製多個副本到其餘機器,知足故障恢復和負載均衡等求.
Redis也是如此,提供了複製功能.
複製功能是高可用Redis的基礎,後面的哨兵和集羣都是在複製的基礎上實現高可用的.git
1.在配置文件中加入slaveof {masterHost} {masterPort} 隨redis啓動生效. 2.在redis-server啓動命令後加入—slaveof {masterHost} {masterPort}生效. 3.直接使用命令:slaveof {masterHost} {masterPort}生效. #查看複製狀態信息命令 Info replication
快速建立第二臺redis節點命令: rsync -avz db01:/opt/* /opt/ rm -rf /data (先備份) mkdir /data/redis_6379/ -p cd /opt/redis make install sed -i 's#51#52#g' /opt/redis_6379/conf/redis_6379.conf redis-server /opt/redis_6379/conf/redis_6379.conf 配置方法: 方法1: 臨時生效 [root@db-02 ~]# redis-cli -h 10.0.0.52 10.0.0.52:6379> SLAVEOF 10.0.0.51 6379 OK 方法2: 寫入配置文件 SLAVEOF 10.0.0.51 6379 取消主從複製 SLAVEOF no one 注意!!! 1.從節點只讀不可寫 2.從節點不會自動故障轉移,它會一直同步主 10.0.0.52:6379> set k1 v1 (error) READONLY You can't write against a read only slave. 3.主從複製故障轉移須要人工介入 - 修改代碼指向REDIS的IP地址 - 從節點須要執行SLAVEOF no one 注意!!! 1.從節點會清空本身原有的數據,若是同步的對象寫錯了,就會致使數據丟失 2.主庫有密碼從庫的配置 masterauth 123456 安全的操做: 1.不管是同步,不管是主節點仍是從節點 2.先備份一下數據 3.配置持久化(爲了從新載入數據) 4.重啓
從節點請求同步: 2602:S 09 Nov 15:58:25.703 * The server is now ready to accept connections on port 6379 2602:S 09 Nov 15:58:25.703 * Connecting to MASTER 10.0.1.51:6379 2602:S 09 Nov 15:58:25.703 * MASTER <-> SLAVE sync started 2602:S 09 Nov 15:58:25.703 * Non blocking connect for SYNC fired the event. 2602:S 09 Nov 15:58:25.703 * Master replied to PING, replication can continue... 2602:S 09 Nov 15:58:25.704 * Partial resynchronization not possible (no cached master) 2602:S 09 Nov 15:58:25.705 * Full resync from master: be1ed4812a0bd83227af30dc6ebe36d88bca5005:1 主節點收到請求以後開始持久化保存數據: 12703:M 09 Nov 15:58:25.708 * Slave 10.0.1.52:6379 asks for synchronization 12703:M 09 Nov 15:58:25.708 * Full resync requested by slave 10.0.1.52:6379 12703:M 09 Nov 15:58:25.708 * Starting BGSAVE for SYNC with target: disk 12703:M 09 Nov 15:58:25.708 * Background saving started by pid 12746 12746:C 09 Nov 15:58:25.710 * DB saved on disk 12746:C 09 Nov 15:58:25.710 * RDB: 6 MB of memory used by copy-on-write 從節點接收主節點發送的數據,而後載入內存: 2602:S 09 Nov 15:58:25.805 * MASTER <-> SLAVE sync: receiving 95 bytes from master 2602:S 09 Nov 15:58:25.805 * MASTER <-> SLAVE sync: Flushing old data 2602:S 09 Nov 15:58:25.805 * MASTER <-> SLAVE sync: Loading DB in memory 2602:S 09 Nov 15:58:25.806 * MASTER <-> SLAVE sync: Finished with success 主節點收到從節點同步完成的消息: 12703:M 09 Nov 15:58:25.809 * Background saving terminated with success 12703:M 09 Nov 15:58:25.809 * Synchronization with slave 10.0.1.52:6379 succeeded 主從複製流程: 1.從節點發送同步請求到主節點 2.主節點接收到從節點的請求以後,作了以下操做 - 當即執行bgsave將當前內存裏的數據持久化到磁盤上 - 持久化完成以後,將rdb文件發送給從節點 3.從節點從主節點接收到rdb文件以後,作了以下操做 - 清空本身的數據 - 載入從主節點接收的rdb文件到本身的內存裏 4.後面的操做就是和主節點實時的了
Redis Sentinel 是一個分佈式系統, Redis Sentinel爲Redis提供高可用性。能夠在沒有人爲干預的狀況下阻止某種類型的故障。
Redis 的 Sentinel 系統用於管理多個 Redis 服務器(instance)該系統執行如下三個任務:
1.監控(Monitoring):
Sentinel 會不斷地按期檢查你的主服務器和從服務器是否運做正常。
2.提醒(Notification):
當被監控的某個 Redis 服務器出現問題時, Sentinel 能夠經過 API 向管理員或者其餘應用程序發送通知。
3.自動故障遷移(Automatic failover):
當一個主服務器不能正常工做時, Sentinel 會開始一次自動故障遷移操做, 它會將失效主服務器的其中一個從服務器升級爲新的主服務器, 並讓失效主服務器的其餘從服務器改成複製新的主服務器; 當客戶端試圖鏈接失效的主服務器時, 集羣也會向客戶端返回新主服務器的地址, 使得集羣可使用新主服務器代替失效服務器github
Sentinel 節點是一個特殊的 Redis 節點,他們有本身專屬的 API(端口)redis
哨兵是基於主從複製,因此須要先部署好主從複製 手工操做步驟以下: 1.先配置和建立好1臺服務器的節點和哨兵 2.使用rsync傳輸到另外2臺機器 3.修改另外兩臺機器的IP地址 建議使用ansible劇本批量部署
1.db03上執行快速安裝第3個redis節點 rsync -avz 10.0.0.51:/opt/* /opt/ mkdir /data/redis_6379 -p cd /opt/redis make install sed -i 's#51#53#g' /opt/redis_6379/conf/redis_6379.conf redis-server /opt/redis_6379/conf/redis_6379.conf redis-cli 2.啓動全部的單節點 redis-server /opt/redis_6379/conf/redis_6379.conf 3.配置主從複製(任意節點) redis-cli -h 10.0.0.52 slaveof 10.0.0.51 6379 redis-cli -h 10.0.0.53 slaveof 10.0.0.51 6379
!!!!注意!!!!算法
==三個節點的bind IP修改成本身的IP地址==sql
mkdir -p /data/redis_26379 mkdir -p /opt/redis_26379/{conf,pid,logs} #.配置哨兵的配置文件 注意!三臺機器都操做 cat >/opt/redis_26379/conf/redis_26379.conf << EOF bind $(ifconfig eth0|awk 'NR==2{print $2}') port 26379 daemonize yes logfile /opt/redis_26379/logs/redis_26379.log dir /data/redis_26379 sentinel monitor myredis 10.0.0.51 6379 2 sentinel down-after-milliseconds myredis 3000 sentinel parallel-syncs myredis 1 sentinel failover-timeout myredis 18000 EOF #.啓動哨兵 redis-sentinel /opt/redis_26379/conf/redis_26379.conf #.驗證主節點(注意對應的節點) redis-cli -h 10.0.0.51 -p 26379 Sentinel get-master-addr-by-name myredis redis-cli -h 10.0.0.52 -p 26379 Sentinel get-master-addr-by-name myredis redis-cli -h 10.0.0.53 -p 26379 Sentinel get-master-addr-by-name myredis
當全部節點啓動後,配置文件的內容發生了變化,體如今三個方面:shell
1)Sentinel節點自動發現了從節點,其他Sentinel節點 2)去掉了默認配置,例如parallel-syncs failover-timeout參數 3)添加了配置紀元相關參數
查看配置文件命令數據庫
[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
1.查詢命令:CONFIG GET slave-priority 2.設置命令:CONFIG SET slave-priority 0 3.主動切換(哨兵):sentinel failover myredis redis-cli -h 10.0.0.52 -p 6379 CONFIG SET slave-priority 0 redis-cli -h 10.0.0.53 -p 6379 CONFIG SET slave-priority 0 redis-cli -h 10.0.0.51 -p 26379 sentinel failover myredis
redis-cli -h 10.0.0.51 -p 26379 Sentinel get-master-addr-by-name myredis
主從密碼配置文件裏添加2行參數: requirepass "123456" masterauth "123456" 哨兵配置文件添加一行參數: sentinel auth-pass myredis 123456
1.查看權重 CONFIG GET slave-priority 2.設置權重 在其餘節點把權重設爲0 CONFIG SET slave-priority 0 3.主動發起從新選舉 sentinel failover mymaster 4.恢復默認的權重 CONFIG SET slave-priority 100
Redis Cluster 是 redis的分佈式解決方案,在3.0版本正式推出
當遇到單機、內存、併發、流量等瓶頸時,能夠採用Cluster架構方案達到負載均衡目的。
Redis Cluster以前的分佈式方案有兩種:
分佈式數據庫首先要解決把整個數據庫集按照分區規則映射到多個節點的問題,即把數據集劃分到多個節點上,每一個節點負責總體數據的一個子集,須要關注的數據分片規則,redis cluster
ciyong哈希分片規則
思路:
拓撲圖
主節點 6380 從節點 6381 # redis安裝目錄 /opt/redis_{6380,6381}/{conf,logs,pid} # redis數據目錄 /data/redis_{6380,6381} # redis運維腳本 /root/scripts/redis_shell.sh
#爲了關閉其餘redis端口,生產中須要注意 pkill redis mkdir -p /opt/redis_{6380,6381}/{conf,logs,pid} mkdir -p /data/redis_{6380,6381} cat >/opt/redis_6380/conf/redis_6380.conf<<EOF bind 10.0.0.51 port 6380 daemonize yes pidfile "/opt/redis_6380/pid/redis_6380.pid" logfile "/opt/redis_6380/logs/redis_6380.log" dbfilename "redis_6380.rdb" dir "/data/redis_6380/" cluster-enabled yes cluster-config-file nodes_6380.conf cluster-node-timeout 15000 EOF cd /opt/ 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_638* 10.0.0.52:/opt/ rsync -avz /opt/redis_638* 10.0.0.53:/opt/ redis-server /opt/redis_6380/conf/redis_6380.conf redis-server /opt/redis_6381/conf/redis_6381.conf ps -ef|grep redis
pkill redis find /opt/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#51#52#g" mkdir –p /data/redis_{6380,6381} redis-server /opt/redis_6380/conf/redis_6380.conf redis-server /opt/redis_6381/conf/redis_6381.conf ps -ef|grep redis
pkill redis find /opt/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#51#53#g" mkdir –p /data/redis_{6380,6381} redis-server /opt/redis_6380/conf/redis_6380.conf redis-server /opt/redis_6381/conf/redis_6381.conf ps -ef|grep redis
當把全部節點都啓動後查看進程會有cluster的字樣,可是登陸後執行CLUSTER NODES命令會發現只有每一個節點本身的ID,目前集羣內的節點,尚未互相發現,因此搭建redis集羣咱們第一步要作的就是讓集羣內的節點互相發現.,在執行節點發現命令以前咱們先查看一下集羣的數據目錄會發現有生成集羣的配置文件,查看後發現只有本身的節點內容,等節點所有發現後會把所發現的節點ID寫入這個文件
集羣模式的Redis除了原有的配置文件以外又加了一份集羣配置文件.當集羣內節點. 信息發生變化,如添加節點,節點下線,故障轉移等.節點會自動保存集羣狀態到配置文件.
須要注意的是,Redis自動維護集羣配置文件,不須要手動修改,防止節點重啓時產生錯亂.
節點發現使用命令: CLUSTER MEET {IP} {PORT}
提示:在集羣內任意一臺機器執行此命令就能夠
redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.51 6381 redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.52 6380 redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.52 6381 redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.53 6380 redis-cli -h 10.0.0.51 -p 6380 CLUSTER MEET 10.0.0.53 6381
redis-cli -h 10.0.0.51 -p 6380 CLUSTER NODES [root@db01 opt]# redis-cli -h 10.0.0.51 -p 6380 CLUSTER NODES 0a138d3b47ae0ac83719d150ac5e46f1986c92f9 10.0.0.52:6381 master - 0 1577372412387 3 connected f1c6d6a418edb08f986715f093934646d92f99e3 10.0.0.53:6381 master - 0 1577372411377 0 connected dc225e89785179d0045d82a2b3f0c1d072466713 10.0.0.53:6380 master - 0 1577372410361 4 connected 10922-16383 81b466115f32423ecd32a2cb4477f1e1a9913437 10.0.0.52:6380 master - 0 1577372408341 5 connected 5461-10921 83d86340bf4859023994ba75f4b1d84778a58840 10.0.0.51:6381 master - 0 1577372413402 2 connected b0cda45c78d5a7fe288f46fa85c4041da795a5ec 10.0.0.51:6380 myself,master - 0 0 1 connected 0-5460
在分佈式存儲中須要提供維護節點元數據信息的機制,所謂元數據是指:節點負責哪些數據,是否出現故障燈狀態信息,redis 集羣採用 Gossip(流言)協議,Gossip 協議工做原理就是節點彼此不斷交換信息,一段時間後全部的節點都會知道集羣完整信息,這種方式相似流言傳播。
通訊過程:
==集羣中的每個節點都會單獨開闢一個 Tcp 通道,用於節點之間彼此通訊,通訊端口在基礎端口上家10000==.
每一個節點在固定週期內經過特定規則選擇結構節點發送 ping 消息
接收到 ping 消息的節點用 pong 消息做爲響應。集羣中每一個節點經過必定規則挑選要通訊的節點,每一個節點可能知道所有節點,也可能僅知道部分節點,只要這些節點彼此能夠正常通訊,最終他們會打成一致的狀態,當節點出現故障,新節點加入,主從角色變化等,它可以給不斷的ping/pong消息,從而達到同步目的。
Gossip
Gossip 協議職責就是信息交換,信息交換的載體就是節點間彼此發送Gossip 消息。
常見 Gossip 消息分爲:ping、 pong、 meet、 fail 等
meet
meet 消息:用於通知新節點加入,消息發送者通知接受者加入到當前集羣,meet 消息
通訊正常完成後,接收節點會加入到集羣中並進行ping、 pong 消息交換
ping
ping 消息:集羣內交換最頻繁的消息,集羣內每一個節點每秒想多個其餘節點發送 ping 消息,用於檢測節點是否在線和交換彼此信息。
pong
Pong 消息:當接收到 ping,meet 消息時,做爲相應消息回覆給發送方確認消息正常通訊,節點也能夠向集羣內廣播自身的 pong 消息來通知整個集羣對自身狀態進行更新。
fail
fail 消息:當節點斷定集羣內另外一個節點下線時,迴向集羣內廣播一個fail 消息,其餘節點收到 fail 消息以後把對應節點更新爲下線狀態。
通信示意圖:
redis集羣一共有16384個槽,全部的槽都必須分配完畢,
有一個槽沒分配整個集羣都不可用,每一個節點上槽位的順序無所謂,重點是槽位的個數,
hash分片算法足夠隨機,足夠平均
不要去手動修改集羣的配置文件
咱們雖然有6個節點,可是真正負責數據寫入的只有3個節點,其餘的3個節點只是做爲主節點的從節點,也就是說,只須要分配期中三個節點的的槽位就能夠
非配槽位須要在每一個主節點上來配置,兩種方法執行:
db01:6380 0-5460 db02:6380 5461-10921 db03:6380 10922-16383
redis-cli -h 10.0.0.51 -p 6380 CLUSTER ADDSLOTS {0..5460} redis-cli -h 10.0.0.52 -p 6380 CLUSTER ADDSLOTS {5461..10920} redis-cli -h 10.0.0.52 -p 6380 CLUSTER ADDSLOTS 10921 redis-cli -h 10.0.0.53 -p 6380 CLUSTER ADDSLOTS {10922..16383}
redis-cli -h db01 -p 6380 CLUSTER info
雖然這時候集羣是可用的了,可是整個集羣只要有一臺機器壞掉了,那麼整個集羣都是不可用的.
因此這時候須要用到其餘三個節點分別做爲如今三個主節點的從節點,以應對集羣主節點故障時能夠進行自動切換以保證集羣持續可用.
注意:
1.不要讓複製節點複製本機器的主節點, 由於若是那樣的話機器掛了集羣仍是不可用狀態, 因此複製節點要複製其餘服務器的主節點.
2.使用redis-trid工具自動分配的時候會出現複製節點和主節點在同一臺機器上的狀況,須要注意
#查詢id redis-cli -h 10.0.0.51 -p 6380 CLUSTER NODES redis-cli -h 10.0.0.51 -p 6381 CLUSTER REPLICATE 35b5ee70a887b5256089a5eebf521aa21a0a7a7a redis-cli -h 10.0.0.52 -p 6381 CLUSTER REPLICATE 65baaa3b071f906c14da10452c349b0871317210 redis-cli -h 10.0.0.53 -p 6381 CLUSTER REPLICATE a1d47ccb19411eaf12d5af4b22cafbbefc8e2486
1.嘗試插入一條數據發現報錯 10.0.0.51:6380> set k1 v1 (error) MOVED 12706 10.0.0.53:6380 2.目前的現象 - 在db01的6380節點插入數據提示報錯 - 報錯內容提示應該移動到db03的6380上 - 在db03的6380上執行相同的插入命令能夠插入成功 - 在db01的6380節點插入數據有時候能夠,有時候不行 - 使用-c參數後,能夠正常插入命令,而且節點切換到了提示的對應節點上 3.問題緣由 由於集羣模式又ASK路由規則,加入-c參數後,會自動跳轉到目標節點處理 而且最後由目標節點返回信息 4.測試足夠隨機足夠平均 #!/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
sh redis_shell.sh login 6380 10.0.0.52 [root@db03 script]# cat redis_shell.sh #!/bin/bash USAG(){ echo "sh $0 {start|stop|restart|login|ps|tail} PORT" } if [ "$#" = 1 ] then REDIS_PORT='6379' elif [ "$#" -gt 2 -a -z "$(echo "$2"|sed 's#[0-9]##g')" ] then REDIS_PORT="$2" else USAG exit 0 fi REDIS_IP=$3 PATH_DIR=/opt/redis_${REDIS_PORT}/ PATH_CONF=/opt/redis_${REDIS_PORT}/conf/redis_${REDIS_PORT}.conf PATH_LOG=/opt/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
至此,咱們已經手動的把一個redis高可用的集羣部署完畢了, 可是尚未模擬過故障
這裏咱們就模擬故障,停掉期中一臺主機的redis節點,而後查看一下集羣的變化
咱們使用暴力的kill -9殺掉 db02上的redis集羣節點,而後觀察節點狀態
理想狀況應該是db01上的6381從節點升級爲主節點
在db01上查看集羣節點狀態
雖然咱們已經測試了故障切換的功能,可是節點修復後仍是須要從新上線
因此這裏測試節點從新上線後的操做
從新啓動db02的6380,而後觀察日誌
觀察db01上的日誌
這時假如咱們想讓修復後的節點從新上線,能夠在想變成主庫的從庫執行CLUSTER FAILOVER命令
這裏咱們在db02的6380上執行
在集羣模式下,Redis接受任何鍵相關命令時首先會計算鍵對應的槽,再根據槽找出所對應的節點 若是節點是自身,則處理鍵命令;不然回覆MOVED重定向錯誤,通知客戶端請求正確的節點,這個過程稱爲Mover重定向.
知道了ask路由後,咱們使用-c選項批量插入一些數據
手動搭建集羣便於理解集羣建立的流程和細節,不過手動搭建集羣須要不少步驟,當集羣節點衆多時,必然會加大搭建集羣的複雜度和運維成本,所以官方提供了 redis-trib.rb的工具方便咱們快速搭建集羣。
redis-trib.rb是採用 Ruby 實現的 redis 集羣管理工具,內部經過 Cluster相關命令幫咱們簡化集羣建立、檢查、槽遷移和均衡等常見運維操做,使用前要安裝 ruby 依賴環境
1.安裝依賴-只要在db01上操做 yum makecache fast yum install rubygems -y gem sources --remove https://rubygems.org/ gem sources -a http://mirrors.aliyun.com/rubygems/ gem update –system gem install redis -v 3.3.5 2.還原環境-全部節點都執行!!! pkill redis rm -rf /data/redis_6380/* rm -rf /data/redis_6381/* 3.啓動集羣節點-全部節點都執行 redis-server /opt/redis_6380/conf/redis_6380.conf redis-server /opt/redis_6381/conf/redis_6381.conf ps -ef|grep redis 4.使用工具搭建部署Redis(一臺部署) cd /opt/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 5.檢查集羣完整性 ./redis-trib.rb check 10.0.0.51:6380 6.檢查集羣負載是否合規 ./redis-trib.rb rebalance 10.0.0.51:6380
redis集羣的擴容操做規劃
擴容流程圖
打印出進羣每一個節點信息後,reshard命令須要確認遷移的槽數量,這裏咱們輸入4096個: How many slots do you want to move (from 1 to 16384)? 4096 輸入6390的節點ID做爲目標節點,也就是要擴容的節點,目標節點只能指定一個 What is the receiving node ID? xxxxxxxxx 以後輸入源節點的ID,這裏分別輸入每一個主節點的6380的ID最後輸入done,或者直接輸入all Source node #1:all 遷移完成後命令會自動退出,這時候咱們查看一下集羣的狀態 ./redis-trib.rb rebalance 10.0.0.51:6380
1.建立新節點-db01操做 mkdir -p /opt/redis_{6390,6391}/{conf,logs,pid} mkdir -p /data/redis_{6390,6391} cd /opt/ 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 redis-server /opt/redis_6390/conf/redis_6390.conf redis-server /opt/redis_6391/conf/redis_6391.conf ps -ef|grep redis 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 redis-cli -c -h db01 -p 6380 cluster nodes 2.使用工具擴容步驟 cd /opt/redis/src/ ./redis-trib.rb reshard 10.0.0.51:6380 第一次交互:每一個節點保留多少個槽位 How many slots do you want to move (from 1 to 16384)? 4096 第二次交互:接收節點的ID是什麼 What is the receiving node ID? 6390的ID 第三次交互:哪一個節點須要導出 Source node #1: all 第四次交互:確認是否執行分配 Do you want to proceed with the proposed reshard plan (yes/no)? yes 3.檢查集羣完整性 ./redis-trib.rb check 10.0.0.51:6380 4.檢查集羣負載是否合規 ./redis-trib.rb rebalance 10.0.0.51:6380 5.調整複製順序 redis-cli -h 10.0.0.53 -p 6381 CLUSTER REPLICATE 51-6390的ID redis-cli -h 10.0.0.51 -p 6391 CLUSTER REPLICATE 51-6380的ID 6.測試寫入腳本 [root@db01 ~]# cat for.sh #!/bin/bash for i in $(seq 1 100000) do redis-cli -c -h db01 -p 6380 set k_${i} v_${i} && echo "set k_${i} is ok" done 7.測試讀腳本 [root@db03 ~]# cat du.sh #!/bin/bash for i in $(seq 1 100000) do redis-cli -c -h db01 -p 6380 get k_${i} sleep 0.1 done
流程說明
redis-trib.rb reshard
命令只能有一個目標節點,所以須要執行3次reshard命令,分別遷移1365,1365,1366個槽收縮流程圖
1.使用工具收縮節點 cd /opt/redis/src/ ./redis-trib.rb reshard 10.0.0.51:6380 2.第一次交互: 要遷移多少個 How many slots do you want to move (from 1 to 16384)? 1365 3.第二次交互: 輸入第一個須要接收節點的ID What is the receiving node ID? db01的6380的ID 4.第三次交互: 輸入須要導出的節點的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: db01的6390的ID Source node #2: done 5.第四次交互: 確認 Do you want to proceed with the proposed reshard plan (yes/no)? yes 6.繼續重複的操做,直到6390全部的槽位都分配給了其餘主節點 7.確認集羣狀態是否正常,確認6390槽位是否都遷移走了 10.0.0.51:6380> CLUSTER NODES 8.忘記以及下線節點(從節點能夠直接刪除,主節點先移走數據,再刪除) ./redis-trib.rb del-node 10.0.0.51:6390 baf9585a780d9f6e731972613a94b6f3e6d3fb5e ./redis-trib.rb del-node 10.0.0.51:6391 e54a79cca258eb76fb74fc12dafab5ebac26ed90
首先肯定端口是否啓動
檢查防火牆,getenforce
./redis-trib.rb check 10.0.0.51:6380檢查
cluster nodes
遷移過程當中,ctrl+c,集羣出現問題
解決辦法:
工具關閉槽 cd /opt/redis/src ./redis-trib.rb fix 10.0.0.51:6380 手動關閉: 鏈接對應的redis節點,執行cluster setslot 773 stable,(導入,導出問題槽位)
1手動關閉: 鏈接對應的redis節點,執行cluster setslot 773 stable, 查詢槽的狀態已經恢復 cluster info 檢查,有報錯, ./redis-trib.rb check 10.0.0.51:6380 cluster info 狀態ok,集羣用fix,有問題,發現問題773槽位識別出現問題,其餘節點上看0-773在6390上,6390上看而在6380上 2.刪除兩個問題槽位,6380,6390 cluster delslots 773 3.6390添加773 cluster addslots 773 發現你們看到的結果一致6390上,check.reblance ok
集羣(cluster) CLUSTER INFO 打印集羣的信息 CLUSTER NODES 列出集羣當前已知的全部節點(node),以及這些節點的相關信息。 節點(node) CLUSTER MEET <ip> <port> 將 ip 和 port 所指定的節點添加到集羣當中,讓它成爲集羣的一份子。 CLUSTER FORGET <node_id> 從集羣中移除 node_id 指定的節點。 CLUSTER REPLICATE <node_id> 將當前節點設置爲 node_id 指定的節點的從節點。 CLUSTER SAVECONFIG 將節點的配置文件保存到硬盤裏面。 槽(slot) CLUSTER ADDSLOTS <slot> [slot ...] 將一個或多個槽(slot)指派(assign)給當前節點。 CLUSTER DELSLOTS <slot> [slot ...] 移除一個或多個槽對當前節點的指派。 CLUSTER FLUSHSLOTS 移除指派給當前節點的全部槽,讓當前節點變成一個沒有指派任何槽的節點。 CLUSTER SETSLOT <slot> NODE <node_id> 將槽 slot 指派給 node_id 指定的節點,若是槽已經指派給另外一個節點,那麼先讓另外一個節點刪除該槽>,而後再進行指派。 CLUSTER SETSLOT <slot> MIGRATING <node_id> 將本節點的槽 slot 遷移到 node_id 指定的節點中。 CLUSTER SETSLOT <slot> IMPORTING <node_id> 從 node_id 指定的節點中導入槽 slot 到本節點。 CLUSTER SETSLOT <slot> STABLE 取消對槽 slot 的導入(import)或者遷移(migrate)。 鍵 (key) CLUSTER KEYSLOT <key> 計算鍵 key 應該被放置在哪一個槽上。 CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的鍵值對數量。CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 個 slot 槽中的鍵。
需求背景
剛切換到redis集羣的時候確定會面臨數據導入的問題,因此這裏推薦使用redis-migrate-tool工具來導入單節點數據到集羣裏
官方地址:
http://www.oschina.net/p/redis-migrate-tool
1.安裝工具 yum install libtool autoconf automake git bzip2 -y cd /opt/ git clone https://github.com/vipshop/redis-migrate-tool.git cd redis-migrate-tool/ autoreconf -fvi ./configure make && make install 2.編寫配置文件 cat > 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 EOF 3.單節點生成測試數據 redis-server /opt/redis_6379/conf/redis_6379.conf cat >input_6379.sh<<EOF #!/bin/bash for i in {1..1000} do redis-cli -c -h db01 -p 6379 set oldzhang_\${i} oldzhang_\${i} echo "set oldzhang_\${i} is ok" done EOF 4.運行工具遷移單節點數據到集羣 redis-migrate-tool -c 6379_to_6380.conf 5.運行工具驗證數據是否遷移完成 redis-migrate-tool -c 6379_to_6380.conf -C redis_check
1.先把集羣的RDB文件都收集起來 - 在從節點上執行bgsave命令生成RDB文件 redis-cli -h db01 -p 6381 BGSAVE redis-cli -h db02 -p 6381 BGSAVE redis-cli -h db03 -p 6381 BGSAVE 2.把從節點生成的RDB文件拉取過來 mkdir /root/rdb_backup cd /root/rdb_backup/ scp db01:/data/redis_6381/redis_6381.rdb db01_6381.rdb scp db02:/data/redis_6381/redis_6381.rdb db02_6381.rdb scp db03:/data/redis_6381/redis_6381.rdb db03_6381.rdb 3.清空數據 redis-cli -c -h db01 -p 6380 flushall redis-cli -c -h db02 -p 6380 flushall redis-cli -c -h db03 -p 6380 flushall 7.編寫配置文件 cat >rdb_to_cluter.conf <<EOF [source] type: rdb file servers: - /root/rdb_backup/db01_6381.rdb - /root/rdb_backup/db02_6381.rdb - /root/rdb_backup/db03_6381.rdb [target] type: redis cluster servers: - 10.0.0.51:6380 [common] listen: 0.0.0.0:8888 source_safe: true EOF 8.使用工具導入 redis-migrate-tool -c rdb_to_cluter.conf
需求背景
redis的內存使用太大鍵值太多,不知道哪些鍵值佔用的容量比較大,並且在線分析會影響性能
0.需求背景 redis的內存使用太大鍵值太多,不知道哪些鍵值佔用的容量比較大,並且在線分析會影響性能. 1.安裝命令:(pip可能會出錯,) yum install python-pip gcc python-devel -y cd /opt/ git clone https://github.com/sripathikrishnan/redis-rdb-tools cd redis-rdb-tools pip install python-lzf python setup.py install 2.生成測試數據: redis-cli -h db01 -p 6379 set txt $(cat txt.txt) 3.執行bgsave生成rdb文件 redis-cli -h db01 -p 6379 BGSAVE 3.使用工具分析: cd /data/redis_6379/ rdb -c memory redis_6379.rdb -f redis_6379.rdb.csv 4.過濾分析 awk -F"," '{print $4,$3}' redis_6379.rdb.csv |sort -n 5.將結果整理彙報給領導,詢問開發這個key是否能夠刪除
設置內存最大限制 config set maxmemory 2G 內存回收機制 當達到內存使用限制以後redis會出發對應的控制策略 redis支持6種策略: 1.noevicition 默認策略,不會刪除任務數據,拒絕全部寫入操做並返回客戶端錯誤信息,此時只響應讀操做 2.volatile-lru 根據LRU算法刪除設置了超時屬性的key,指導騰出足夠空間爲止,若是沒有可刪除的key,則退回到noevicition策略 3.allkeys-lru 根據LRU算法刪除key,無論數據有沒有設置超時屬性 4.allkeys-random 隨機刪除全部key 5.volatile-random 隨機刪除過時key 5.volatile-ttl 根據key的ttl,刪除最近要過時的key 動態配置 config set maxmemory-policy
需求背景
由於開發重複提交,致使電商網站優惠捲過時時間失效
問題分析
若是一個鍵已經設置了過時時間,這時候在set這個鍵,過時時間就會取消
解決思路
如何在不影響機器性能的前提下批量獲取須要監控鍵過時時間
1.Keys * 查出來匹配的鍵名。而後循環讀取ttl時間
2.scan * 範圍查詢鍵名。而後循環讀取ttl時間
Keys 重操做,會影響服務器性能,除非是不提供服務的從節點
Scan 負擔小,可是須要去屢次才能取完,須要寫腳本
腳本內容:
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