需求和基础了解
应用场景
1.缓存-键过期时间
把session会话存在redis,过期删除
缓存用户信息,缓存Mysql部分数据,用户先访问redis,redis没有再访问mysql,然后回写给redis
商城优惠卷过期时间
2.排行榜-列表&有序集合
热度/点击数排行榜
直播间礼物积分排行
3.计数器-天然支持计数器
帖子浏览数
视频播放数
评论数
点赞/踩
4.社交网络-集合
粉丝
共同好友
兴趣爱好
标签
5.消息队列-发布订阅
配合ELK缓存收集来的日志
多种数据结构
字符串,哈希,列表,集合,有序集合,地理位置
数据持久化
所有的数据都运行在内存中
支持2种格式持久化数据AOF RDB AOF&RDB
自带多种高可用架构
主从
哨兵
集群
redis官网
https://redis.io/
版本选择
2.x very old
3.x redis-cluster
4.x 混合持久化
5.x 新增加了流处理类型 最新稳定版
规划目录
/app/soft 下载目录
/app/redis_6379/{conf,logs,pid} 安装目录,日志目录,pid目录,配置目录
/app/data/redis_6379/ 数据目录
192.168.67.11 redis01
192.168.67.12 redis02
192.168.67.13 redis03
一 Redis主从复制模式
1.1 安装命令:redis01和redis02分别安装
mkdir /app/soft -p
cd /app/soft
wget http://download.redis.io/releases/redis-5.0.7.tar.gz
tar zxf redis-5.0.7.tar.gz -C /app/
ln -s /app/redis-5.0.7 /app/redis
cd /app/redis
yum install wget gcc make -y
make
make install
1.2 配置文件
mkdir -p /app/redis_6379/{conf,pid,logs}
mkdir -p /app/data/redis_6379
cat >/app/redis_6379/conf/redis_6379.conf<< EOF
daemonize yes
bind 127.0.0.1 192.168.67.11
port 6379
pidfile /app/redis_6379/pid/redis_6379.pid
logfile /app/redis_6379/logs/redis_6379.log
appendonly yes
appendfilename "redis.aof"
appendfsync everysec
EOF
更完善的配置参考,哨兵模式的
port 6379
#端口
cluster-enabled no
#开启集群功能
cluster-config-file "nodes-6379.conf"
#集群配置文件
cluster-node-timeout 5000
#集群节点超时时间,单位毫秒
cluster-slave-validity-factor 2
#选主超时,计算方式(node-timeout * slave-validity-factor+ repl-ping-slave-period)
appendonly no
#开启AOF模式
appendfsync everysec
#everysec:每秒写入一次aof
#always:每一次写入都写一次aof,性能较差
#no:交给操作系统来维护,操作系统默认330s
maxmemory 3906250kb
#最大内存
maxmemory-policy volatile-lru
#内存不足时清除策略
#noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错
#allkeys-lru:在主键空间中,优先移除最近未使用的key。
#volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。
#allkeys-random:在主键空间中,随机移除某个key。
#volatile-random:在设置了过期时间的键空间中,随机移除某个key。
#volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。
bind 0.0.0.0
#绑定IP
dir "/data/redis"
#持久化文件路径
appendfilename "appendonly.aof"
#保存数据的aof名称
daemonize yes
#后台运行
pidfile "redis.pid"
#pid文件
auto-aof-rewrite-min-size 1000000000
#最小重写aof大小,小于这个值不触发重写
#requirepass redis
logfile "redis.log"
loglevel notice
#禁用keys *
rename-command KEYS ""
#rdb持久化
#dbfilename dump.rdb
#save 900 1
#save 300 10
#save 60 10000
requirepass "password"
masterauth "password"
#cluster-slave-no-failover yes
# Generated by CONFIG REWRITE
slaveof 192.168.67.11 6379
1.3 启动命令和检查
redis-server /app/redis_6379/conf/redis_6379.conf
ps -ef|grep redis
netstat -lntup|grep 6379
1.4 system启动配置:$(ifconfig ens33|awk 'NR==2{print $2}')为当前主机ip
groupadd -g 1000 redis
useradd redis -u 1000 -g 1000 -M -s /sbin/nologin
chown -R redis:redis /app/redis*
chown -R redis:redis /app/data/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-server /app/redis_6379/conf/redis_6379.conf --supervised systemd
ExecStop=/usr/local/bin/redis-cli -h $(ifconfig ens33|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
1.5 在redis01插入测试命令
for i in {1..1000};do redis-cli -h 192.168.67.11 set ${i} ${i};done
1.6 配置主从复制,在redis02上执行
#方法1:临时生效
redis-cli -h 192.168.67.12 slaveof 192.168.67.11 6379
#方法2:写进配置文件
slaveof 192.168.67.11 6379
1.7 redis02断开主从连接
127.0.0.1:6379> slaveof no one
1.8 查看主从信息
#主库上执行
redis-cli -h 192.168.67.11 info Replication
#从库上执行
redis-cli -h 192.168.67.12 info Replication
1.9 redis02 数据没有同步过来故障
#查看日志
[root@redis02 ~]# tail -f /app/redis_6379/logs/redis_6379.log
29161:S 24 Feb 2021 01:12:10.941 * MASTER <-> REPLICA sync started
29161:S 24 Feb 2021 01:12:11.949 # Error condition on socket for SYNC: No route to host
#检查主库redis01的防火墙
systemctl status firewalld
iptables -nL
1.10 简单流程
(1)从节点发送同步请求到主节点
(2)主节点接收到从节点的请求之后,做了如下操作
- 立即执行bgsave将当前内存里的数据持久化到磁盘上
- 持久化完成之后,将rdb文件发送给从节点
(3)从节点从主节点接收到rdb文件之后,做了如下操作
- 清空自己的数据
- 载入从主节点接收的rdb文件到自己的内存里
(4)后面的操作就是和主节点实时的了
1.11 主从复制注意
(1)从节点只读不可写
(2)从节点不会自动故障转移,它会一直同步主节点
192.168.67.12: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)业务低峰期操作。
二 Redis哨兵模式
2.1 哨兵的作用
解决了主从复制故障需要人为干预的问题
提供了自动的高可用解决方案
2.2 目录和端口规划
redis节点: 6379
哨兵节点: 26379
2.3 部署redis节点
按上述方式分别在redis01,redis02,redis03 装好redis单节点,并启动。
2.4 配置主从复制
在redis02上执行
redis-cli -h 192.168.67.12 slaveof 192.168.67.11 6379
在redis03上执行
redis-cli -h 192.168.67.13 slaveof 192.168.67.11 6379
在redis01主库上执行
redis-cli -h 192.168.67.11 info Replication
2.5部署哨兵节点-3台机器都操作
mkdir -p /app/data/redis_26379
mkdir -p /app/redis_26379/{conf,pid,logs}
cat >/app/redis_26379/conf/redis_26379.conf << EOF
bind $(ifconfig eth0|awk 'NR==2{print $2}')
port 26379
daemonize yes
logfile /app/redis_26379/logs/redis_26379.log
dir /app/data/redis_26379
sentinel monitor myredis 192.168.67.11 6379 2
sentinel down-after-milliseconds myredis 3000
sentinel parallel-syncs myredis 1
sentinel failover-timeout myredis 18000
EOF
chown -R redis:redis /app/data/redis*
chown -R redis:redis /app/redis*
参数解释:
sentinel monitor mymaster 192.168.67.11 6379 2
#mymaster 主节点别名 主节点 ip 和端口, 判断主节点失败, 两个 sentinel 节点同意
sentinel down-after-milliseconds mymaster 3000
#选项指定了 Sentinel 认为服务器已经断线所需的毫秒数。
sentinel parallel-syncs mymaster 1
#向新的主节点发起复制操作的从节点个数, 1 轮询发起复制
sentinel failover-timeout mymaster 180000
#故障转移超时时间.
更完善的配置参考
port 26379
dir "/data/redis"
logfile "26379.log"
daemonize yes
bind 0.0.0.0
sentinel myid f5cdfgshfhdsy457ce152f7fwrtw53
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 192.168.67.11 6379 2
sentinel down-after-milliseconds mymaster 10000
sentinel auth-pass mymaster password
sentinel config-epoch mymaster 11
# Generated by CONFIG REWRITE
sentinel leader-epoch mymaster 11
sentinel known-slave mymaster 192.168.67.12 6379
sentinel known-slave mymaster 192.168.67.13 6379
sentinel known-sentinel mymaster 192.168.67.12 6379 6e08aff6a1c77fgsdrtwt9742c765938f2820c2
sentinel known-sentinel mymaster 192.168.67.13 6379 5d23308208517cdarewrq410a588575ed2fb13b1
sentinel current-epoch 11
2.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 /app/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
2.7启动哨兵并检查
systemctl daemon-reload
systemctl start redis-sentinel
哨兵登录,查看主从节点(此步骤为故障转移后redis02为主节点后查看的内容)
[root@redis01 redis_6379]# redis-cli -h 192.168.67.11 -p 26379
192.168.67.11:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=myredis,status=ok,address=192.168.67.12:6379,slaves=2,sentinels=3
哨兵查看主节点
192.168.67.11:26379> sentinel masters
1) 1) "name"
2) "myredis"
3) "ip"
4) "192.168.67.12"
5) "port"
6) "6379"
7) "runid"
8) "6a896c807d0fb8c84c08aeb38572ce1b2b09da97"
9) "flags"
10) "master"
11) "link-pending-commands"
可以这样查看主节点
192.168.67.11:26379> sentinel get-master-addr-by-name myredis
1) "192.168.67.12"
2) "6379"
哨兵查看从节点(myredis为组名)
192.168.67.11:26379> sentinel slaves myredis
1) 1) "name"
2) "192.168.67.11:6379"
3) "ip"
4) "192.168.67.11"
5) "port"
6) "6379"
7) "runid"
8) "82bf4fa1839
2.8验证主节点
redis-cli -h 192.168.67.11 -p 26379 Sentinel get-master-addr-by-name myredis
redis-cli -h 192.168.67.12 -p 26379 Sentinel get-master-addr-by-name myredis
redis-cli -h 192.168.67.13 -p 26379 Sentinel get-master-addr-by-name myredis
2.9模拟故障转移
#关闭主节点服务上的所有redis进程
pkill redis
#观察其他2个节点会不会发生选举
redis-cli -h 192.168.67.12 -p 26379 Sentinel get-master-addr-by-name myredis
redis-cli -h 192.168.67.13 -p 26379 Sentinel get-master-addr-by-name myredis
redis-cli -h 192.168.67.12 info Replication
#查看配置文件里会不会自动更新
cat /app/redis_26379/conf/redis_26379.conf
#查看新的主节点能不能写入
set k3 v3
#查看从节点能否正常同步
get k3
2.10 模拟故障修复上线
#redis01上执行
#启动单节点
systemctl start redis
#启动哨兵
systemctl start redis-sentinel
#检查确认
redis-cli -h 192.168.67.12 info Replication
看到redis02被选举为主节点了。
2.11 能够给redis 节点加权 (强制重新选举,故障转移)来确定优先备选主节点嘛?
查询命令(redis命令执行):CONFIG GET slave-priority
设置命令(redis命令执行):CONFIG SET slave-priority 0
主动切换(哨兵命令执行) :sentinel failover myredis
默认优先级都为100
127.0.0.1:6379> CONFIG GET slave-priority
1) "slave-priority"
2) "100"
假如要指定redis01被切换为主节点,把redis02和redis03的设置为0最低级别。
redis-cli -h 192.168.67.12 -p 6379 CONFIG SET slave-priority 0
redis-cli -h 192.168.67.13 -p 6379 CONFIG SET slave-priority 0
redis-cli -h 192.168.67.11 -p 26379 sentinel failover myredis
验证
redis-cli -h 192.168.67.11 -p 26379 Sentinel get-master-addr-by-name myredis
redis-cli -h 192.168.67.12 -p 26379 Sentinel get-master-addr-by-name myredis
redis-cli -h 192.168.67.13 -p 26379 Sentinel get-master-addr-by-name myredis
最后把刚才设置的设为100
redis-cli -h 192.168.67.12 -p 6379 CONFIG SET slave-priority 100
redis-cli -h 192.168.67.13 -p 6379 CONFIG SET slave-priority 100
三 集群模式
3.1集群重要概念
redis集群,无论有几个节点,一共只有16384个槽
所有的槽位都必须分配,哪怕有1个槽位不正常,整个集群都不能用
每个节点的槽的顺序不重要,重点是数量
hash算法足够随机,足够平均
每个槽被分配到数据的概率是相当的
集群的高可用依赖于主从复制
集群拥有自己的配置文件,动态更新,不要手欠修改
集群通讯会使用基础端口号+10000的端口,这个是自动创建的,不是配置文件配置的
集群槽位分配比例允许误差在%2之间
3.2目录规划
主节点 6380 (默认会加有16380通信端口,即加10000,网络权限打通时要注意,6380和16380都要开通)
从节点 6381 (默认会加有16381通信端口, 即口加10000,网络权限打通时要注意,6381和16381都要开通)
3.3安装和配置
redis01 redis02 redis03的操作,注意每个节点的ip。
注意集群配置文件 nodes_6380.conf默认在定义的数据目录下dir "/app/data/redis_6380/"
pkill redis
mkdir -p /app/redis_{6380,6381}/{conf,logs,pid}
mkdir -p /app/data/redis_{6380,6381}
cat >/app/redis_6380/conf/redis_6380.conf<<EOF
bind 192.168.67.11
port 6380
daemonize yes
pidfile "/app/redis_6380/pid/redis_6380.pid"
logfile "/app/redis_6380/logs/redis_6380.log"
dbfilename "redis_6380.rdb"
dir "/app/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 /app/
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 /app/redis_*
chown -R redis:redis /app/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 /app/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
查看节点命令
redis-cli -h 192.168.67.11 -p 6380 CLUSTER NODES
de339c4f7173d074de78d9bb031d7614b9379b5d :6380@16380 myself,master - 0 0 0 connected
3.4集群手动发现节点(在任意节点上可执行)
redis-cli -h 192.168.67.11 -p 6380 CLUSTER MEET 192.168.67.12 6380
redis-cli -h 192.168.67.11 -p 6380 CLUSTER MEET 192.168.67.13 6380
redis-cli -h 192.168.67.11 -p 6380 CLUSTER MEET 192.168.67.11 6381
redis-cli -h 192.168.67.11 -p 6380 CLUSTER MEET 192.168.67.12 6381
redis-cli -h 192.168.67.11 -p 6380 CLUSTER MEET 192.168.67.13 6381
redis-cli -h 192.168.67.11 -p 6380 CLUSTER NODES
3.5集群手动分配槽位
1 槽位规划
redis01:6380 5461 0-5460
redis02:6380 5461 5461-10921
redis03:6380 5462 10922-16383
2 分配槽位(可以在同一台执行,redis支持远程操作,只要有一个槽位没分配,整个集群都不能用)
计算方式3个主节点,16384/3 =5461
redis-cli -h 192.168.67.11 -p 6380 CLUSTER ADDSLOTS {0..5460}
redis-cli -h 192.168.67.12 -p 6380 CLUSTER ADDSLOTS {5461..10921}
redis-cli -h 192.168.67.13 -p 6380 CLUSTER ADDSLOTS {10922..16383}
3.6 查看集群状态
redis-cli -h 192.168.67.11 -p 6380 CLUSTER NODES
redis-cli -h 192.168.67.11 -p 6380 CLUSTER INFO
3.7 插入数据验证-集群模式加-c
[root@redis01 redis_6380]# redis-cli -h 192.168.67.11 -p 6380 set tang3 bin3
(error) MOVED 12033 192.168.67.13:6380
报错原因,经过hash算法,这个数据应该到192.168.67.13节点插入。
使用-c参数后,可以正常插入命令,并且节点切换到了提示的对应节点上
通过命令redis-cli -h 帮助可以看到
[root@redis01 redis_6380]# redis-cli -h 192.168.67.11 -p 6380 -c set tang4 bin4
redis-cli -h 192.168.67.11 -p 6381 -c get tang4
redis-cli -h 192.168.67.12 -p 6381 -c get tang4
redis-cli -h 192.168.67.13 -p 6381 -c get tang4
问题原因
因为集群模式有ASK路由规则,加入-c参数后,会自动跳转到目标节点处理
并且最后由目标节点返回信息
结论集群登录要添加-c
redis-cli -h 192.168.67.11 -p 6380 -c
3.8 建立从主复制关系
redis-cli -h 192.168.67.11 -p 6380 CLUSTER NODES
先删除所有6381的内容和不需要内容
8d1ca7d93a99cb2cd59af6e97df7ba0c75afa22b 192.168.67.12:6381
de339c4f7173d074de78d9bb031d7614b9379b5d 192.168.67.11:6380
4895714edc9c5ec75ac7d3ddad2cb32b995abd01 192.168.67.13:6380
f454f356a2cb52fb9c6893cd6c514f783483e43a 192.168.67.12:6380
b269e62454d5d7d2caf8506d6dd83e4796390c74 192.168.67.13:6381
c1c6928a7d234fa36b4214a54574f4410c8aa3e7 192.168.67.11:6381
集群图
确定复制关系
redis-cli -h 192.168.67.11 -p 6381 CLUSTER REPLICATE 13的6380的ID
redis-cli -h 192.168.67.12 -p 6381 CLUSTER REPLICATE 11的6380的ID
redis-cli -h 192.168.67.13 -p 6381 CLUSTER REPLICATE 12的6380的ID
3.9 执行从节点复制主节点命令
redis-cli -h 192.168.67.11 -p 6381 CLUSTER REPLICATE 4895714edc9c5ec75ac7d3ddad2cb32b995abd01
redis-cli -h 192.168.67.12 -p 6381 CLUSTER REPLICATE de339c4f7173d074de78d9bb031d7614b9379b5d
redis-cli -h 192.168.67.13 -p 6381 CLUSTER REPLICATE f454f356a2cb52fb9c6893cd6c514f783483e43a
验证
redis-cli -h 192.168.67.11 -p 6380 CLUSTER NODES
redis-cli -h 192.168.67.11 -p 6380 CLUSTER INFO
故障:模拟在redis01挂了,pkill redis,集群正常,再启动后
在redis02上看redis-cli -h 192.168.67.11 -p 6380 CLUSTER NODES,发现redis02都为master,都有槽位,这台如果坏了,整个集群就坏了。
de339c4f7173d074de78d9bb031d7614b9379b5d 192.168.67.11:6380@16380 slave 8d1ca7d93a99cb2cd59af6e97df7ba0c75afa22b 0 1614118689172 6 connected
c1c6928a7d234fa36b4214a54574f4410c8aa3e7 192.168.67.11:6381@16381 slave 4895714edc9c5ec75ac7d3ddad2cb32b995abd01 0 1614118684000 3 connected
f454f356a2cb52fb9c6893cd6c514f783483e43a 192.168.67.12:6380@16380 myself,master - 0 1614118685000 0 connected 5461-10921
8d1ca7d93a99cb2cd59af6e97df7ba0c75afa22b 192.168.67.12:6381@16381 master - 0 1614118685054 6 connected 0-5460
4895714edc9c5ec75ac7d3ddad2cb32b995abd01 192.168.67.13:6380@16380 master - 0 1614118688140 2 connected 10922-16383
b269e62454d5d7d2caf8506d6dd83e4796390c74 192.168.67.13:6381@16381 slave f454f356a2cb52fb9c6893cd6c514f783483e43a 0 1614118687112 4 connected
解决方法或规避:
方法1:
redis01机器修复后, 启动92.168.67.11:6380和92.168.67.11:6381,然后将92.168.67.12:6381关闭,让92.168.67.11:6380变成mater,最后92.168.67.12:6381启动。
方法2 (推荐,主动发起集群角色切换):
redis01机器修复后, 启动92.168.67.11:6380和92.168.67.11:6381
systemctl start redis-master
systemctl start redis-slave
然后执行以下主动发起集群角色切换命令
redis-cli -h 192.168.67.11 -p 6380 CLUSTER FAILOVER
验证
redis-cli -h 192.168.67.11 -p 6380 CLUSTER NODES
redis-cli -h 192.168.67.11 -p 6380 CLUSTER INFO
集群命令
redis-cli --cluster info 192.168.67.12 6380
redis-cli --cluster rebalance 192.168.67.12 6380
四 数据导入导出工具
需求背景
刚切换到redis集群的时候肯定会面临数据导入的问题,所以这里推荐使用redis-migrate-tool工具来导入单节点数据到集群里
官方地址:
http://www.oschina.net/p/redis-migrate-tool
安装工具
cd /app/redis_cluster/
git clone https://github.com/vipshop/redis-migrate-tool.git
cd redis-migrate-tool/
autoreconf -fvi
./configure
make && make install
创建配置文件
[root@db01 ~]# cat redis_6379_to_6380.conf
[source]
type: single
servers:
- 192.168.67.11:6379
[target]
type: redis cluster
servers:
- 192.168.67.11:6380
[common]
listen: 0.0.0.0:8888
source_safe: true
执行导入命令
[root@db01 ~]# redis-migrate-tool -c redis_6379_to_6380.conf
数据校验
[root@db01 ~]# redis-migrate-tool -c redis_6379_to_6380.conf -C redis_check
五 分析键值大小
需求背景
redis的内存使用太大键值太多,不知道哪些键值占用的容量比较大,而且在线分析会影响性能.
安装工具
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 /app/data/redis_cluster/redis_6380/
rdb -c memory redis_6380.rdb -f redis_6380.rdb.csv
分析rdb并导出
awk -F ',' '{print $4,$2,$3,$1}' redis_6380.rdb.csv |sort > 6380.txt
六 实战-槽位分配错误如何调整
1.故障背景
某日某豪接到任务,需要部署redis集群结果不小心无脑复制粘贴,把所有的槽都分配给了1个节点,还没发现,然后就交付使用了,过了1天才发现问题。
而此时,已经有不少数据写入了,如何在不丢失数据的情况下解决这个问题?
2.前提
数据不能丢,最好不中断业务
3.实验现象
[root@db01 ~]# redis-cli --cluster info 192.168.67.11 6380
192.168.67.11:6380 (ccaa5dcb...) -> 1000 keys | 16384 slots | 3 slaves.
192.168.67.12:6380 (a69e46ea...) -> 0 keys | 0 slots | 0 slaves.
192.168.67.13:6380 (b2719c41...) -> 0 keys | 0 slots | 0 slaves.
[OK] 1000 keys in 3 masters.
0.06 keys per slot on average.
解决
解决思路1:备份数据,重做集群,导入数据
实验结论:
重启后所有的数据还是在redis01上。
redis01重启后数据虽然可以写入,但是访问的时候还是按照正常的hash规则去分配的,所以db01的数据实际上是没用的。
所以这样的方法是不可行的。
解决思路2: 流水线 pipline
前提条件:
1.了解aof格式
2.了解新版本redis默认是开启混合模式的
3.需要修改为普通的aof格式并重启
4.恢复时使用-c参数无效,需要在每一个节点都执行
命令:
进到redis.aof的目录cd /app/data/redis_6380
redis-cli -c -h 192.168.67.11 -p 6380 --pipe < redis.aof
redis-cli -c -h 192.168.67.12 -p 6380 --pipe < redis.aof
redis-cli -c -h 192.168.67.13 -p 6380 --pipe < redis.aof
解决思路3: 使用redis-cli工具重新分配槽位(推荐)
重新分配槽位
redis-cli --cluster reshard 192.168.67.11:6380
第一次交互:输入迁出的槽的数量
How many slots do you want to move (from 1 to 16384)? 5461
第二次交互:输入接受的ID
What is the receiving node ID? redis02的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: redis01的6390的ID
Source node #2: done
第四次交互:YES!
重复上面的操作,知道所有的节点槽位都分配正确
解决思路4:直接使用工具在线导入
redis-cli --cluster import 192.168.67.11:6380 --cluster-copy --cluster-replace --cluster-from 192.168.67.11:6379
添加replace参数会覆盖掉同名的数据,对新集群新增加的数据不受影响
添加copy参数相当于cp,老数据迁移成功后会保留
不加copy参数相当于mv,老数据迁移成功就删掉了
验证迁移期间边写边导会不会影响: 同时开2个终端,一个写入key
只会导入当你执行导入命令那一刻时,当前被导入节点的所有数据,类似于快照,对于后面再写入的数据不会更新
七 集群扩容
创建新节点6390 6391 步骤省略
使用工具扩容步骤
重新分配槽位
redis-cli --cluster reshard 192.168.67.11: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
八 使用工具缩容
操作命令
重新分配槽位
redis-cli --cluster reshard 192.168.67.11:6380
第一次交互:需要迁移多少个槽位
How many slots do you want to move (from 1 to 16384)? 1365
第二次交互:接受节点的ID是什么
What is the receiving node ID? redis01的6380的ID
第三次交互:哪些节点需要导出
Source node #1: redis01的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 192.168.67.11:6380
使用工具删除节点了
redis-cli --cluster del-node 192.168.67.11:6390 6390的ID
redis-cli --cluster del-node 192.168.67.11:6391 6391的ID