Redis-5.x

第1章 關係型與非關係型

關係型: mysql oracle
非關係型:redis mongo ES

第2章 Redis重要特性 AK47

1.速度快
c語言寫的
代碼優雅
單線程架構
2.支持多種數據結構
字符串,哈希,列表,集合,有序集合,地理位置
3.豐富的功能
天然計數器
健過期功能
消息隊列
4.支持客戶端語言多
php,java,python
5.數據持久化
所有的數據都運行在內存中
支持2種格式持久化數據AOF RDB AOF&RDB
6.自帶多種高可用架構
主從
哨兵
集羣

第3章 redis應用場景

1.緩存-鍵過期時間
把session會話存在redis,過期刪除
緩存用戶信息,緩存Mysql部分數據,用戶先訪問redis,redis沒有再訪問mysql,然後回寫給redis
商城優惠捲過期時間
2.排行榜-列表&有序集合
熱度/點擊數排行榜
直播間禮物積分排行
3.計數器-天然支持計數器
帖子瀏覽數
視頻播放數
評論數
點贊/踩
4.社交網絡-集合
粉絲
共同好友
興趣愛好
標籤
5.消息隊列-發佈訂閱
配合ELK緩存收集來的日誌

第4章 Redis安裝部署

1.redis官網

https://redis.io/

2.版本選擇

2.x very old
3.x redis-cluster
4.x 混合持久化
5.x 新增加了流處理類型 最新穩定版

3.規劃目錄

/data/soft 下載目錄
/opt/redis_6379/{conf,logs,pid} 安裝目錄,日誌目錄,pid目錄,配置目錄
/data/redis_6379/ 數據目錄

4.安裝命令

mkdir /data/soft -p
cd /data/soft
wget http://download.redis.io/releases/redis-5.0.7.tar.gz
tar xf redis-5.0.7.tar.gz -C /opt/
ln -s /opt/redis-5.0.7 /opt/redis
cd /opt/redis
make
make install

5.配置文件

mkdir -p /opt/redis_6379/{conf,pid,logs}
mkdir -p /data/redis_6379
cat >/opt/redis_6379/conf/redis_6379.conf<< EOF
daemonize yes
bind 127.0.0.1 10.0.0.51
port 6379
pidfile /opt/redis_6379/pid/redis_6379.pid
logfile /opt/redis_6379/logs/redis_6379.log
EOF

6.啓動命令

redis-server /opt/redis_6379/conf/redis_6379.conf

7.檢查

ps -ef|grep redis
netstat -lntup|grep 6379

8.連接redis終端

[root@db01 ~]# redis-cli
127.0.0.1:6379>
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
“v1”
127.0.0.1:6379>

9.關閉命令

kill
pkill
redis-cli

SHUTDOWN

  • redis-cli shutdown

10.system啓動配置

groupadd -g 1000 redis
useradd -u 1000 -g 1000 -M -s /sbin/nologin
chown -R redis:redis /data/redis*
chown -R redis:redis /opt/redis*
cat >/usr/lib/systemd/system/redis.service<<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/redis /opt/redis_6379/conf/redis_6379.conf --supervised systemd
ExecStop=/usr/local/bin/redis-cli -h $(ifconfig eth0|awk ‘NR==2{print $2}’) -p 6379 shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl start redis

第5章 Redis全局命令

全局命令是指對所有數據類型都通用的命令

0.redis數據格式

key:value
鍵:值

1.寫入測試key

set k1 v1
set k2 v2
set k3 v3

2.查看所有的key

!!!危險命令!!!此操作未滿30歲禁止請在家人的看管下執行

keys *

3.查看有多少個key

DBSIZE

4.查看某個Key是否存在

EXISTS k1

狀態碼:
0 表示這個key不存在
1 表示這個key存在
N 表示存在N個key

5.刪除key

DEL k1
DEL k1 k2

狀態碼:
0 表示這個key不存在
1 表示這個key存在,並且刪除成功了
N 表示N個key存在,並且刪除成功了N個key

6.鍵過期

設置過期時間

EXPIRE k1 10

狀態碼:
0 這個key不存在
1 這個key存在,並且設置過期時間成功
查看keys是否過期

TTL k1

狀態碼:
-1 這個key存在,並且沒有設定存活週期,永不過期
-2 這個key不存在
N 這個key存在,並且在N秒後過期
取消過期時間:

第一種方法:
PERSIST k1

第二種方法:
set k1 v1

結論:
過期後的key會被直接刪除

第6章 字符串操作

1.設置一個key

set k1 v1

2.查看一個key

get k1

3.設置多個key

MSET k1 v1 k2 v2 k3 v3 k4 v4

4.查看多個key

MGET k1 k2 k3 k4

5.天然計數器

加1:
SET k1 1
INCR k1
GET k1

加N:
INCRBY k1 100

減1:
INCRBY k1 -1

減N:
INCRBY k1 -100

第7章 列表操作

1.插入列表

LPUSH: 從列表左側插入數據
RPUSH: 從列表右側插入數據

2.查看列表長度

LLEN list1

3.查看列表內容

LRANGE list1 0 -1

4.刪除列表元素

LPOP: 從列表左邊刪除一個元素
RPOP: 從列表右邊刪除一個元素

LPOP list1
RPOP list1

5.刪除整個列表

DEL list1

第8章 hash操作

1.mysql數據如何緩存到redis

mysql存儲格式:
user
id name job age
1 bobo IT 28
2 json py 25
3 hao bug 26

hash類型存儲格式:
key field value field value
user:1 name bobo job IT age 28
user:2 name json job py age 25
user:3 name hao job bug age 26

2.創建一個Hash數據

HMSET user:1 name bobo job IT age 28
HMSET user:2 name json job py age 29
HMSET user:3 name hao job bug age 19

3.查看hash裏指定的值

select name from user where id =1 ;

HMGET user:1 name
HMGET user:1 name job age

4.查看Hash裏所有的值

select * from user where id =1 ;

HGETALL user:1

第9章 集合操作 set

1.創建集合

SADD set1 1 2 3
SADD set2 1 3 5 7

2.查看集合成員

SMEMBERS set1
SMEMBERS set2

3.查看集合的交集

127.0.0.1:6379> SINTER set1 set2

  1. “1”
  2. “3”

4.查看集合的並集

127.0.0.1:6379> SUNION set1 set2

  1. “1”
  2. “2”
  3. “3”
  4. “5”
  5. “7”

5.查看集合的差集

127.0.0.1:6379> SDIFF set1 set2

  1. “2”

127.0.0.1:6379> SDIFF set2 set1

  1. “5”
  2. “7”

6.刪除一個成員

SREM set1 1

6.注意

集合不允許出現重複的值,自動去重

第10章 有序集合操作

1.添加成員

ZADD SZ3 100 json
ZADD SZ3 90 bobo
ZADD SZ3 99 xiaocancan
ZADD SZ3 98 bughao

2.計算成員個數

ZCARD SZ3

3.計算某個成員分數

ZSCORE SZ3 json

4.按照降序查看成員名次:

ZRANK SZ3 json
ZRANK SZ3 bobo

5.按照升序查看成員名次:

ZREVRANK SZ3 json
ZREVRANK SZ3 bobo

6.刪除成員

ZREM SZ3 json

7.增加成員分數

ZINCRBY SZ3 2 xiaocancan
ZSCORE SZ3 xiaocancan

8.返回指定排名範圍的成員

ZRANGE SZ3 0 3
ZRANGE SZ3 0 3 WITHSCORES

9.返回指定分數範圍的成員

ZRANGEBYSCORE SZ3 95 100
ZRANGEBYSCORE SZ3 95 100 WITHSCORES

10.返回指定分數範圍的成員的個數

ZCOUNT SZ3 90 110

第11章 持久化

在這裏插入圖片描述
RDB流程圖
在這裏插入圖片描述
AOF流程圖

1.RDB和AOF介紹

RDB:類似於快照的形式,當前內存裏的狀態持久化到硬盤裏
優點:壓縮格式/恢復速度快
缺點:不是實時的,可能會丟失數據,操作比較重

AOF:類似於mysql的binlog,可以設置爲每秒/每次操作以追加的形式持久化
優點:安全,最多損失1秒的數據,可讀
缺點:文件比較大,恢復速度慢

2.配置RDB

save 900 1
save 300 10
save 60 10000
dbfilename redis.rdb
dir /data/redis_6379/

3.RDB結論

1.沒有配置save參數時,shutdown不會持久化保存
2.沒有配置save參數時,可以手動執行bgsave觸發持久化
3.在配置了save參數後,shutdown,kill,pkill都會自動觸發bgsave
4.恢復的時候,rdb文件名要和配置文件裏寫的一樣。
5.RDB高版本兼容低版本,低版本不兼容高版本

4.AOF配置

appendonly yes
appendfilename “redis.aof”
appendfsync everysec

5.AOF重寫機制

執行的命令 aof記錄 redis的數據
set k1 v1 set k1 k1
set k2 v2 set k2 k1 k2
set k3 v3 set k3 k1 k2 k3
del k1 del k1 k2 k3
del k2 del k2 k3
實際有意義的只有一條記錄:
set k3

6.aof和rdb實驗

實驗背景:

aof和rdb同時存在的時候,redis重啓會讀取哪一個數據?
實驗步驟:

set k1 v1
set k2 v2
bgsave
RDB k1 k2
mv redis.rdb /opt/

flushall
set k3 v3
set k4 v4
AOF k3 k4
mv redis.aof /opt/

pkill redis
rm -rf /data/redis_6379/*
mv /opt/redis.rdb .
mv /opt/redis.aof .

redis-server /opt/redis_6379/conf/redis.conf
redis-cli
keys *
結論:

當aof和rdb同時存在時,重啓redis會優先讀取aof的內容

7.如何選擇是rdb還是aof

https://redis.io/topics/persistence
1.開啓混合模式
2.開啓aof
3.不開啓rdb
4.rdb採用定時任務的方式定時備份

8.aof文件故障模擬實驗結論

1.aof文件損壞之後,使用修復工具,一刀流,從aof文件出錯的地方開始到最後全部刪掉
2.任何操作之前,先備份數據
3.aof備份一般情況最多損失1秒的數據

9.實驗:如果設置了過期時間,恢復數據會如何處理

1.aof文件會記錄下過期的時間
2.恢復的時候會去對比記錄的過期時間和當前時間,如果超過了,就刪除key
3.key的過期時間不受備份恢復影響

第12章 redis用戶認證

1.寫入配置文件

requirepass cookzhang

2.使用密碼登陸

第一種:

[root@db01 ~]# redis-cli
127.0.0.1:6379> AUTH cookzhang
OK
127.0.0.1:6379> set k1 v1
OK

第二種:

redis-cli -a cookz get k1

3.爲什麼redis的密碼認證這麼簡單?

1.redis一般都部署在內網環境,默認是比較安全的環境
2.有同學擔心密碼寫在配置文件裏,開發不允許登陸到Linux服務器上,但是可以連接到redis,設個密碼安全些

第13章 禁用或重命名危險命令

1.禁用危險命令

rename-command CONFIG “”
rename-command KEYS “”
rename-command SHUTDOWN “”
rename-command FLUSHALL “”
rename-command DEL “”
rename-command FLUSHDB “”

2.來自json的靈魂拷問:shutdown禁用了 讓後用kill?

rename-command CONFIG “”
rename-command KEYS “”
rename-command SHUTDOWN “qq526195417”
rename-command FLUSHALL “”
rename-command DEL “byebye”
rename-command FLUSHDB “”

第14章 Redis主從複製

1.快速部署第二臺服務器

rsync -avz 10.0.0.51:/opt/* /opt/*
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

2.db01插入測試命令

for i in {1…1000};do redis-cli -h 10.0.0.51 set ${i} ${i};done

3.配置主從複製

方法1:臨時生效

redis-cli -h 10.0.0.52 slaveof 10.0.0.51 6379
方法2:寫進配置文件

slaveof 10.0.0.51 6379

4.主從複製的流程

1.簡單流程:

1.從節點發送同步請求到主節點
2.主節點接收到從節點的請求之後,做了如下操作

  • 立即執行bgsave將當前內存裏的數據持久化到磁盤上
  • 持久化完成之後,將rdb文件發送給從節點
    3.從節點從主節點接收到rdb文件之後,做了如下操作
  • 清空自己的數據
  • 載入從主節點接收的rdb文件到自己的內存裏
    4.後面的操作就是和主節點實時的了

5.取消複製

SLAVEOF no one

6.主從複製注意

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
    4.從節點會清空自己原有的數據,如果同步的對象寫錯了,就會導致數據丟失
    5.從庫和主庫後續的同步依靠的是redis的SYNC協議,而不是RDB文件,RDB文件只是第一次建立同步時使用。
    6.從庫也可以正常的持久化文件

7.安全的操作

無論是同步,無論是主節點還是從節點,請先備份一下數據

第15章 Redis哨兵

在這裏插入圖片描述

1.哨兵的作用

1.解決了主從複製故障需要人爲干預的問題
2.提供了自動的高可用解決方案

2.目錄和端口規劃

redis節點: 6379
哨兵節點: 26379

3.部署3臺redis單節點

db01操作:

pkill redis
cat >/opt/redis_6379/conf/redis_6379.conf <<EOF
daemonize yes
bind 127.0.0.1 10.0.0.51
port 6379
pidfile “/opt/redis_6379/pid/redis_6379.pid”
logfile “/opt/redis_6379/logs/redis_6379.log”
dbfilename “redis.rdb”
dir “/data/redis_6379”
appendonly yes
appendfilename “redis.aof”
appendfsync everysec
EOF
systemctl start redis
redis-cli

db02和db03的操作:

pkill redis
rm -rf /opt/redis*
rsync -avz 10.0.0.51:/usr/local/bin/redis-* /usr/local/bin
rsync -avz 10.0.0.51:/usr/lib/systemd/system/redis.service /usr/lib/systemd/system/
mkdir /opt/redis_6379/{conf,logs,pid} -p
mkdir /data/redis_6379 -p
cat >/opt/redis_6379/conf/redis_6379.conf <<EOF
daemonize yes
bind 127.0.0.1 $(ifconfig eth0|awk ‘NR==2{print $2}’)
port 6379
pidfile “/opt/redis_6379/pid/redis_6379.pid”
logfile “/opt/redis_6379/logs/redis_6379.log”
dbfilename “redis.rdb”
dir “/data/redis_6379”
appendonly yes
appendfilename “redis.aof”
appendfsync everysec
EOF
useradd redis -M -s /sbin/nologin
chown -R redis:redis /opt/redis*
chown -R redis:redis /data/redis*
systemctl daemon-reload
systemctl start redis
redis-cli

4.配置主從複製

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
redis-cli -h 10.0.0.51 info Replication

5.部署哨兵節點-3臺機器都操作

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
chown -R redis:redis /data/redis*
chown -R redis:redis /opt/redis*
參數解釋:

sentinel monitor mymaster 10.0.0.51 6379 2
#mymaster 主節點別名 主節點 ip 和端口, 判斷主節點失敗, 兩個 sentinel 節點同意
sentinel down-after-milliseconds mymaster 3000
#選項指定了 Sentinel 認爲服務器已經斷線所需的毫秒數。
sentinel parallel-syncs mymaster 1
#向新的主節點發起復制操作的從節點個數, 1 輪詢發起複製
sentinel failover-timeout mymaster 180000
#故障轉移超時時間

6.編寫哨兵system配置文件-3臺機器都操作

cat >/usr/lib/systemd/system/redis-sentinel.service<<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/redis-sentinel /opt/redis_26379/conf/redis_26379.conf --supervised systemd
ExecStop=/usr/local/bin/redis-cli -h $(ifconfig eth0|awk ‘NR==2{print $2}’) -p 26379 shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload

7.啓動哨兵並檢查

systemctl start redis-sentinel

8.驗證主節點

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

9.模擬故障轉移

關閉主節點服務上的所有redis進程
觀察其他2個節點會不會發生選舉
查看配置文件裏會不會自動更新
查看新的主節點能不能寫入
查看從節點能否正常同步

10.模擬故障修復上線

啓動單節點
啓動哨兵

11.來自json的靈魂發問:能夠給redis 節點加權 來確定優先備選主節點嘛?

流程說明:
設置其他節點的權重爲0
手動發起重新選舉
觀察所有節點消息是否同步
觀察切換結果是否符合預期

命令解釋:

查詢命令:CONFIG GET slave-priority
設置命令:CONFIG SET slave-priority 0
主動切換: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

第16章 手動部署Redis集羣

集羣架構圖1
在這裏插入圖片描述
集羣架構圖2
在這裏插入圖片描述

1.燒餅的不足

資源利用率不高
主庫壓力大
連接過程繁瑣

2.集羣重要概念

redis集羣,無論有幾個節點,一共只有16384個槽
所有的槽位都必須分配,哪怕有1個槽位不正常,整個集羣都不能用
每個節點的槽的順序不重要,重點是數量
hash算法足夠隨機,足夠平均
每個槽被分配到數據的概率是相當的
集羣的高可用依賴於主從複製
集羣擁有自己的配置文件,動態更新,不要手欠修改
集羣通訊會使用基礎端口號+10000的端口,這個是自動創建的,不是配置文件配置的
集羣槽位分配比例允許誤差在%2之間

3.目錄規劃

主節點 6380
從節點 6381

4.db01的操作

ssh-keygen
ssh-copy-id 10.0.0.52
ssh-copy-id 10.0.0.53
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/”
appendonly yes
appendfilename “redis.aof”
appendfsync everysec
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
chown -R redis:redis /opt/redis_*
chown -R redis:redis /data/redis_*
cat >/usr/lib/systemd/system/redis-master.service<<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/bin/redis-server /opt/redis_6380/conf/redis_6380.conf --supervised systemd
ExecStop=/usr/local/bin/redis-cli -h $(ifconfig eth0|awk ‘NR==2{print $2}’) -p 6380 shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF
cd /usr/lib/systemd/system/
cp redis-master.service redis-slave.service
sed -i ‘s#6380#6381#g’ redis-slave.service
systemctl daemon-reload
systemctl start redis-master
systemctl start redis-slave
ps -ef|grep redis
rsync -avz /opt/redis_638* 10.0.0.52:/opt/
rsync -avz /opt/redis_638* 10.0.0.53:/opt/
rsync -avz /usr/lib/systemd/system/redis-.service 10.0.0.52:/usr/lib/systemd/system/redis-master.service
rsync -avz /usr/lib/systemd/system/redis-
.service 10.0.0.53:/usr/lib/systemd/system/redis-master.service

5.db02的操作

pkill redis
find /opt/redis_638* -type f -name ".conf"|xargs sed -i “/bind/s#51#52#g”
cd /usr/lib/systemd/system/
sed -i ‘s#51#52#g’ redis-
.service
mkdir –p /data/redis_{6380,6381}
chown -R redis:redis /opt/redis_*
chown -R redis:redis /data/redis_*
systemctl daemon-reload
systemctl start redis-master
systemctl start redis-slave
ps -ef|grep redis

6.db03的操作

pkill redis
find /opt/redis_638* -type f -name ".conf"|xargs sed -i “/bind/s#51#53#g”
cd /usr/lib/systemd/system/
sed -i ‘s#51#53#g’ redis-
.service
mkdir –p /data/redis_{6380,6381}
chown -R redis:redis /opt/redis_*
chown -R redis:redis /data/redis_*
systemctl daemon-reload
systemctl start redis-master
systemctl start redis-slave
ps -ef|grep redis

7.集羣手動發現節點

redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.52 6380
redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.53 6380
redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.51 6381
redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.52 6381
redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.53 6381
redis-cli -h db01 -p 6380 CLUSTER NODES

8.集羣手動分配槽位

1.槽位規劃

db01:6380 5461 0-5460
db02:6380 5461 5461-10921
db03:6380 5462 10922-16383

2.分配槽位

redis-cli -h db01 -p 6380 CLUSTER ADDSLOTS {0…5460}
redis-cli -h db02 -p 6380 CLUSTER ADDSLOTS {5461…10921}
redis-cli -h db03 -p 6380 CLUSTER ADDSLOTS {10922…16383}

3.查看集羣狀態

redis-cli -h db01 -p 6380 CLUSTER NODES
redis-cli -h db01 -p 6380 CLUSTER INFO

9.手動部署複製關係

0.先獲取集羣節點信息

redis-cli -h db01 -p 6380 CLUSTER NODES

1.先刪除所有6381的內容和不需要內容

6380的ID 10.0.0.51
6380的ID 10.0.0.53
6380的ID 10.0.0.52

2.畫圖

3.確定複製關係

redis-cli -h db01 -p 6381 CLUSTER REPLICATE 52的6380的ID
redis-cli -h db02 -p 6381 CLUSTER REPLICATE 53的6380的ID
redis-cli -h db03 -p 6381 CLUSTER REPLICATE 51的6380的ID

4.檢查複製關係

redis-cli -h db01 -p 6380 CLUSTER NODES

10.集羣插入數據

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參數後,會自動跳轉到目標節點處理
並且最後由目標節點返回信息

在這裏插入圖片描述

11.驗證集羣是否足夠足跡足夠平均

0.寫入測試數據

for i in {1…10000};do redis-cli -c -h db01 -p 6380 set k_KaTeX parse error: Expected group after '_' at position 6: {i} v_̲{i};echo ${i};done

1.驗證足夠平均:

DBSIZE

2.驗證足夠隨機:

redis-cli -c -h db03 -p 6380 keys * > keys_all.txt
cat keys_all.txt |awk -F “_” ‘{print $2}’|sort -rn

3.允許節點的key在2%誤差的依據來源:

[root@db01 /opt/redis/src]# redis-cli --cluster rebalance 10.0.0.51 6380
、>>> Performing Cluster Check (using node 10.0.0.51:6380)
[OK] All nodes agree about slots configuration.
>>> Check for open slots…
>>> Check slots coverage…
[OK] All 16384 slots covered.
*** No rebalancing needed! All nodes are within the 2.00% threshold.

4.檢查集羣健康狀態:

[root@db01 /opt/redis/src]# redis-cli --cluster info 10.0.0.51 6380
10.0.0.51:6380 (ccaa5dcb…) -> 3343 keys | 5461 slots | 1 slaves.
10.0.0.53:6380 (a69e46ea…) -> 3343 keys | 5462 slots | 1 slaves.
10.0.0.52:6380 (b2719c41…) -> 3314 keys | 5461 slots | 1 slaves.
[OK] 10000 keys in 3 masters.
0.61 keys per slot on average.

第17章 實戰-槽位分配錯誤如何調整

1.故障背景

某日某豪接到任務,需要部署redis集羣結果不小心無腦複製粘貼,把所有的槽都分配給了1個節點,還沒發現,然後就交付使用了,過了1天才發現問題。

而此時,已經有不少數據寫入了,如何在不丟失數據的情況下解決這個問題?

2.前提

數據不能丟,最好不中斷業務

3.實驗現象

[root@db01 ~]# redis-cli --cluster info 10.0.0.51 6380
10.0.0.51:6380 (ccaa5dcb…) -> 1000 keys | 16384 slots | 3 slaves.
10.0.0.53:6380 (a69e46ea…) -> 0 keys | 0 slots | 0 slaves.
10.0.0.52:6380 (b2719c41…) -> 0 keys | 0 slots | 0 slaves.
[OK] 1000 keys in 3 masters.
0.06 keys per slot on average.

解決思路1:備份數據,重做集羣,導入數據

來自json的靈魂發問:
redis.cof的數據 集羣重做後 aof文件裏面的數據能被hash嘛?

備份數據:
redis-cli -c -h db01 -p 6380
db01:6380> BGREWRITEAOF
cp redis.aof redis.aof-1000.bak

重做集羣:
redis-cli -h db01 -p 6380 FLUSHALL
redis-cli -h db02 -p 6380 FLUSHALL
redis-cli -h db03 -p 6380 FLUSHALL

redis-cli -h db01 -p 6380 CLUSTER RESET
redis-cli -h db02 -p 6380 CLUSTER RESET
redis-cli -h db03 -p 6380 CLUSTER RESET

redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.52 6380
redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.53 6380
redis-cli -h db01 -p 6380 CLUSTER NODES

redis-cli -h db01 -p 6380 CLUSTER ADDSLOTS {0…5460}
redis-cli -h db02 -p 6380 CLUSTER ADDSLOTS {5461…10921}
redis-cli -h db03 -p 6380 CLUSTER ADDSLOTS {10922…16383}

redis-cli --cluster info 10.0.0.51 6380

實驗結論:
重啓後所有的數據還是在db01上。
db01重啓後數據雖然可以寫入,但是訪問的時候還是按照正常的hash規則去分配的,所以db01的數據實際上是沒用的。
所以這樣的方法是不可行的。

相關日誌:
16790:M 12 Mar 2020 10:08:08.875 # I have keys for slot 5812, but the slot is assigned to another node. Setting it to importing state.
16790:M 12 Mar 2020 10:08:08.875 # I have keys for slot 5821, but the slot is assigned to another node. Setting it to importing state.
16790:M 12 Mar 2020 10:08:08.875 # I have keys for slot 5842, but the slot is assigned to another node. Setting it to importing state.

解決思路2:獲得所有key的名稱,導出再導入

0.重新制作一個測試集羣,槽位分佈和線上出錯的一樣
1.將線上環境裏的aof導出來
2.恢復到測試的集羣裏
3.收集所有的key
redis-cli -c -h db01 -p 6380 keys * > keys_all.txt
4.編寫腳本遍歷所有的key獲取值
cat >get_key.sh<<EOF
#!/bin/bash
for key in (catkeysall.txt)dovalue=(cat keys_all.txt) do value=(redis-cli -c -h 10.0.0.51 -p 6380 get ${key})
echo redis-cli -c -h 10.0.0.51 -p 6380 set ${key} ${value} >> backup_all_key.txt
done
EOF

5.按照正常槽位分配去重新初始化集羣
redis-cli -h db01 -p 6380 FLUSHALL
redis-cli -h db02 -p 6380 FLUSHALL
redis-cli -h db03 -p 6380 FLUSHALL
redis-cli -h db01 -p 6380 CLUSTER RESET
redis-cli -h db02 -p 6380 CLUSTER RESET
redis-cli -h db03 -p 6380 CLUSTER RESET
redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.52 6380
redis-cli -h db01 -p 6380 CLUSTER MEET 10.0.0.53 6380
redis-cli -h db01 -p 6380 CLUSTER NODES
redis-cli -h db01 -p 6380 CLUSTER ADDSLOTS {0…5460}
redis-cli -h db02 -p 6380 CLUSTER ADDSLOTS {5461…10921}
redis-cli -h db03 -p 6380 CLUSTER ADDSLOTS {10922…16383}
redis-cli --cluster info 10.0.0.51 6380

6.執行導入腳本
bash backup_all_key.txt

7.檢查是否導入成功
redis-cli --cluster info 10.0.0.51 6380

8.測試環境沒問題之後再去生產環境操作

解決思路3: 流水線 pipline

前提條件:
1.瞭解aof格式
2.瞭解新版本redis默認是開啓混合模式的
3.需要修改爲普通的aof格式並重啓
4.恢復時使用-c參數無效,需要在每一個節點都執行

命令:
redis-cli -c -h 10.0.0.51 -p 6380 --pipe < redis.aof
redis-cli -c -h 10.0.0.52 -p 6380 --pipe < redis.aof
redis-cli -c -h 10.0.0.53 -p 6380 --pipe < redis.aof

解決思路4: 使用redis-cli工具重新分配槽位

重新分配槽位
redis-cli --cluster reshard 10.0.0.51:6380

第一次交互:輸入遷出的槽的數量
How many slots do you want to move (from 1 to 16384)? 5461

第二次交互:輸入接受的ID
What is the receiving node ID? db02的6380的ID

第三次交互:輸入發送者的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

第四次交互:YES!

重複上面的操作,知道所有的節點槽位都分配正確

解決思路5:直接使用工具在線導入

redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-replace --cluster-from 10.0.0.51:6379

第18章 使用工具自動部署redis集羣

1.恢復集羣初始化

redis-cli -h db01 -p 6380 FLUSHALL
redis-cli -h db02 -p 6380 FLUSHALL
redis-cli -h db03 -p 6380 FLUSHALL
redis-cli -h db01 -p 6381 FLUSHALL
redis-cli -h db02 -p 6381 FLUSHALL
redis-cli -h db03 -p 6381 FLUSHALL
redis-cli -h db01 -p 6380 CLUSTER RESET
redis-cli -h db02 -p 6380 CLUSTER RESET
redis-cli -h db03 -p 6380 CLUSTER RESET
redis-cli -h db01 -p 6381 CLUSTER RESET
redis-cli -h db02 -p 6381 CLUSTER RESET
redis-cli -h db03 -p 6381 CLUSTER RESET
redis-cli -h db01 -p 6380 CLUSTER NODES

2.使用工具初始化

redis-cli --cluster create 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 --cluster-replicas 1

3.檢查集羣

redis-cli --cluster info 10.0.0.51 6380
redis-cli -h db01 -p 6380 CLUSTER NODES
redis-cli --cluster check 10.0.0.51 6380

第19章 使用工具擴容

在這裏插入圖片描述

1.來自json的靈魂發問:

遷移時候槽的數據咋辦?
需要停庫嗎?
訪問受影響嗎?
從庫呢?

2.如何設計實驗驗證數據是否受影響?

遷移的過程中
一個窗口不斷的寫數據
一個窗口不斷的讀數據
觀察是否會中斷

3.創建新節點

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

4.使用工具擴容步驟

重新分配槽位
redis-cli --cluster 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

第20章 使用工具縮容

在這裏插入圖片描述

1.操作命令

重新分配槽位
redis-cli --cluster reshard 10.0.0.51:6380

第一次交互:需要遷移多少個槽位
How many slots do you want to move (from 1 to 16384)? 1365

第二次交互:接受節點的ID是什麼
What is the receiving node ID? db01的6380的ID

第三次交互:哪些節點需要導出
Source node #1: db01的6390的ID
Source node #2: done

第四次交互:確認
Do you want to proceed with the proposed reshard plan (yes/no)? yes

重複上面的操作,直到6390所有的槽位都被分配出去了

檢查集羣狀態,確認6390沒有槽位了
redis-cli --cluster info 10.0.0.51:6380

使用工具刪除節點了
redis-cli --cluster del-node 10.0.0.51:6390 6390的ID
redis-cli --cluster del-node 10.0.0.51:6391 6391的ID

2.提問:公司先用的是哨兵然後在改集羣 如何遷移數據

用槽位分配解決方法:

1.搭建好Redis集羣並互相發現
2.把所有的key都分配到db01上
3.把哨兵裏的數據AOF持久化
4.拷貝到db01上,啓動集羣節點
5.重新分配槽位遷移到其他2個節點

第21章 .驗證集羣高可用

1.提問:故障的主庫修復後啓動會變成備胎嗎?

2.實驗結論:

1.主庫掛了,從庫會自動接替主庫的角色,集羣恢復正常會受超時時間控制
2.老得主庫修復上線後,會自動變成從庫,同步新的主庫

3.主動發起集羣角色切換:

CLUSTER FAILOVER

第22章 模擬分配時故障

1.模擬場景:遷移數據時人爲中斷了,導致槽的狀態不對

[11213-<-a69e46ea7560684a7061ddb6dc3f854a1ef3dbd4] 51
[11213->-ccaa5dcb0f0320332100594d629122b2702660d5] 53

2.使用工具修復:

redis-cli --cluster fix 10.0.0.51:6380

3.手動修復:

CLUSTER SETSLOT STABLE

第23章 使用工具維護集羣的好處

工具有很多判斷條件,更加嚴謹,健壯性更好
刪除槽,使用工具會判斷,如果槽裏有數據,就不執行
添加節點使用工具會判斷,如果新增加的節點本身不爲空,不允許加入到集羣裏
刪除節點使用工具會判斷,如果本刪除節點本身還有槽,不允許刪除

第24章 數據遷移

1.新版本直接使用工具遷移

不加copy參數相當於mv,老數據遷移成功就刪掉了

redis-cli --cluster import 10.0.0.51:6380 --cluster-from 10.0.0.51:6379
添加copy參數相當於cp,老數據遷移成功後會保留

redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-from 10.0.0.51:6379
添加replace參數會覆蓋掉同名的數據,對新集羣新增加的數據不受影響

redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-replace --cluster-from 10.0.0.51:6379
驗證遷移期間邊寫邊導會不會影響: 同時開2個終端,一個寫入key,

for i in {1…1000};do redis-cli set k_KaTeX parse error: Expected group after '_' at position 6: {i} v_̲{i};sleep 0.2;echo ${i};done
一個執行導入命令

redis-cli --cluster import 10.0.0.51:6380 --cluster-copy --cluster-replace --cluster-from 10.0.0.51:6379
得出結論:

只會導入當你執行導入命令那一刻時,當前被導入節點的所有數據,類似於快照,對於後面再寫入的數據不會更新

第25章 分析key的大小

0.使用自帶工具分析

redis-cli --bigkeys

1.使用第三方工具分析

1.安裝命令

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

4.使用工具分析

cd /data/redis_6379/
rdb -c memory redis_6379.rdb -f redis_6379.rdb.csv

5.過濾分析

awk -F"," ‘{print $4,$3}’ redis_6379.rdb.csv |sort -r

6.彙報領導

將結果整理彙報給領導,詢問開發這個key是否可以刪除

第26章 redis的內存管理

1.設置最大內存限制

config set maxmemory 2G

2.內存回收機制

生產上一定要限制redis的內存使用大小。

當達到內存使用限制之後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

3.生產上redis限制多大內存

先空出來系統一半內存
48G 一共
24G 系統
24G redis
redis先給8G內存 滿了之後,分析結果告訴老大和開發,讓他們排查一下是否所有的key都是必須的
redis再給到12G內存 滿了之後,分析結果告訴老大和開發,讓他們排查一下是否所有的key都是必須的
redis再給到16G內存 滿了之後,分析結果告訴老大和開發,讓他們排查一下是否所有的key都是必須的
等到24G都用完了之後,彙報領導,要考慮買內存了。
等到35G的時候,就要考慮是加內存,還是擴容機器。

第27章 性能測試

redis-benchmark -n 10000 -q

第28章 集羣相關命令

redis-cli -h db01 -p 6380
CLUSTER NODES
CLUSTER MEET 10.0.0.52 6380
CLUSTER INFO
CLUSTER REPLICATE
CLUSTER ADDSLOTS
CLUSTER RESET
CLUSTER FAILOVER
CLUSTER SETSLOT STABLE
redis-cli --cluster info 10.0.0.51 6380
redis-cli --cluster rebalance 10.0.0.51 6380
redis-cli --cluster del-node
redis-cli --cluster fix 10.0.0.51:6380

第29章 命令總結

1.全局命令
keys *
DBSIZE
EXISTS k1
EXPIRE k1 10
TTL k1
DEL k1

2.字符串:
set k1 v1
get k1

mset k1 v1 k2 v2 k3 v3
mget k1 k2 k3

incr k1
incrby k1 N

3.列表:
LPUSH
RPUSH
LPOP
RPOP

LLEN
LRANGE list1 0 -1

HASH:
HMSET
HGET
HMGET
HGETALL

4.集合:
SADD
SDIFF
SINTER
SUNION
SREM

5.有序集合:
ZADD
ZCARD
ZSCORE
ZRANK
ZREVRANK
ZRANGE
ZRANGEBYSCORE
ZINCRBY
ZCOUNT

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