redis有三种集群方式:主从复制,哨兵模式(Sentinel)和集群(Redis Cluster)。
Redis主从为了解决单点问题,通常会把数据复制多个副本到其他机器,满足故障恢复和负载均衡等求,主节点负责写数据,从节点负责读数据,主节点定期把数据同步到从节点保证数据的一致性。
缺点:
Slave启动成功连接到master后会发送一个sync命令;
Master接到命令启动后的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步;
全量复制:而slave服务在数据库文件数据后,将其存盘并加载到内存中;
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步;
但是只要是重新连接master,一次完全同步(全量复制)将被自动执行。
1. 在配置文件中加入slaveof {masterHost} {masterPort} 随redis启动生效.
2. 在redis-server启动命令后加入—slaveof {masterHost} {masterPort}生效.
3. 直接使用命令:slaveof {masterHost} {masterPort}生效.
查看状态信息
info replication
Slaveof命令不但可以建立复制,还可以在从节点执行slave of no one来断开与主节点复制关系.断开复制主要流程:
1. 断开与主节点复制关系
2. 从节点提升为主节点
从节点断开复制后不会抛弃原有数据,只是无法再获取主节点上的数据变化.
Redis的主从模式下,主节点一旦发生故障不能提供服务,需要人工干预,将从节点晋升为主节点,同时还需要修改客户端配置。对于很多应用场景这种方式无法接受。 Sentinel(哨兵)架构解决了redis主从人工干预的问题。 Redis Sentinel是redis的高可用实现方案,实际生产环境中,对提高整个系统可用性非常有帮助的。
Redis Sentinel 是一个分布式系统, Redis Sentinel为Redis提供高可用性。可以在没有人为干预的情况下阻止某种类型的故障。 Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance)该系统执行以下三个任务: 1.监控(Monitoring): Sentinel 会不断地定期检查你的主服务器和从服务器是否运作正常。 2.提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。 3.自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器 架构图:
角色 | IP | 端口 |
---|---|---|
master | 100.1.1.11 | 6379 |
Sentinel-01 | 26379 | |
slave | 100.1.1.12 | 6379 |
Sentinel-01 | 26379 | |
slave | 100.1.1.13 | 6379 |
Sentinel-01 | 26379 |
哨兵是基于主从复制,所以需要先部署好主从复制
redis-01:
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 100.1.1.11
port 26379
daemonize yes
logfile /opt/redis_cluster/redis_26379/logs/redis_26379.log
dir /data/redis_cluster/redis_26379
sentinel monitor mymaster 100.1.1.11 6379 2
sentinel down-after-milliseconds mymaster 3000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 18000
sentinel monitor mymaster 100.1.1.11 6379 2
### mymaster主节点别名 主节点 ip 和端口,判断主节点失败,两个 sentinel 节点同意
sentinel down-after-milliseconds mymaster 30000
#### 选项指定了 Sentinel 认为服务器已经断线所需的毫秒数。
sentinel parallel-syncs mymaster 1
### 向新的主节点发起复制操作的从节点个数,1轮询发起复制
sentinel failover-timeout mymaster 180000
### 故障转移超时时间
在redis01
上把配置推向其他节点
rsync -avz /opt/redis_cluster/ redis02:/opt/
rsync -avz /opt/redis_cluster/ redis03:/opt/
redis02上操作
mkdir -p /data/redis_cluster/redis_26379
cd /opt/redis_cluster/redis
make install
sed -i 's#bind 100.1.1.11#bind 100.1.1.12#g' /opt/redis_cluster/redis_6379/conf/redis_6379.conf
sed -i 's#bind 100.1.1.11#bind 100.1.1.12#g' /opt/redis_cluster/redis_26379/conf/redis_26379.conf
redis03上操作
mkdir -p /data/redis_cluster/redis_26379
cd /opt/redis_cluster/redis
make install
sed -i 's#bind 100.1.1.11#bind 100.1.1.13#g' /opt/redis_cluster/redis_6379/conf/redis_6379.conf
sed -i 's#bind 100.1.1.11#bind 100.1.1.13#g' /opt/redis_cluster/redis_26379/conf/redis_26379.conf
redis02和redis03
上操作:
redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf
redis-cli slaveof 100.1.1.11 6379
ps -ef|grep redis
三台都有操作:
redis-sentinel /opt/redis_cluster/redis_26379/conf/redis_26379.conf
当所有节点启动后,配置文件的内容发生了变化,体现在三个方面:
1)Sentinel节点自动发现了从节点,其余Sentinel节点
2)去掉了默认配置,例如parallel-syncs failover-timeout参数
3)添加了配置纪元相关参数
查看配置文件命令
[root@redis01 ~]# tail -6 /opt/redis_cluster/redis_26379/conf/redis_26379.conf
# Generated by CONFIG REWRITE
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel known-slave mymaster 100.1.1.13 6379
sentinel known-slave mymaster 100.1.1.12 6379
sentinel known-sentinel mymaster 100.1.1.12 26379 9e58bc9da458fefe18b1c499839040a8b0ffd76c
sentinel known-sentinel mymaster 100.1.1.13 26379 b81b8931766c405ae9a9e43663980f2d3a0d1e4a
sentinel current-epoch 0
登陆命令
[root@redis01 ~]# redis-cli -h redis01 -p 26379
# Sentinel节点是一个特殊的Redis节点,他们有自己专属的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
停掉其中1个节点,然后观察其他节点的日志变化 故障转移后配置文件变化 Redis Sentinel存在多个从节点时,如果想将指定的从节点晋升为主节点,可以将其他从节点的slavepriority配置为0,但是需要注意failover后,将slave-priority调回原值.
1.查询命令:CONFIG GET slave-priority
2.设置命令:CONFIG SET slave-priority 0
3.主动切换:sentinel failover mymaster
操作过程:
redis02/redis03操作
redis-cli -h redis02 -p 6379 CONFIG SET slave-priority 0
redis-cli -h redis03 -p 6379 CONFIG SET slave-priority 0
redis01操作
redis-cli -h redis01 -p 26379 Sentinel failover mymaster
Redis Cluster 是 redis的分布式解决方案,在3.0版本正式推出 当遇到单机、内存、并发、流量等瓶颈时,可以采用Cluster架构方案达到负载均衡目的。 Redis Cluster之前的分布式方案有两种: 1) 客户端分区方案,优点分区逻辑可控,缺点是需要自己处理数据路由,高可用和故障转移等。 2) 代理方案,优点是简化客户端分布式逻辑和升级维护便利,缺点加重架构部署和性能消耗。 官方提供的 Redis Cluster集群方案,很好的解决了集群方面的问题。
分布式数据库首先要解决把整个数据库集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整体数据的一个子集,需要关注的是数据分片规则,Redis Cluster采用哈希分片规则。
Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。集群中的每个节点负责处理一部分哈希槽。 举个例子, 一个集群可以有三个节点, 其中:
这样可以轻松地添加和删除集群中的节点。例如,如果我想添加一个新的节点D,我需要将一些哈希槽从节点A、B、C移动到D。类似地,如果我想从集群中删除节点A,我只需将A提供的哈希槽移动到B和C。当节点A为空时,我可以将它完全从集群中删除。
### redis安装目录
/opt/redis_cluster/redis_{PORT}/{conf,logs,pid}
### redis数据目录
/data/redis_cluster/redis_{PORT}/redis_{PORT}.rdb
### redis运维脚本
/root/redis_shell.sh
redis01操作:
### 创建安装目录
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 100.1.1.11
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
### 生成6381配置文件
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* redis02:/opt/redis_cluster/
rsync -avz /opt/redis_cluster/redis_638* redis03:/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
redis02操作:
find /opt/redis_cluster/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#11#12#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
redis03操作:
find /opt/redis_cluster/redis_638* -type f -name "*.conf"|xargs sed -i "/bind/s#11#13#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
当把所有节点都启动后查看进程会有cluster的字样
登录后执行CLUSTER NODES命令会发现只有每个节点自己的ID,目前集群内的节点还没有互相发现,所以搭建redis集群我们第一步要做的就是让集群内的节点互相发现。 节点发现使用命令: CLUSTER MEET {IP} {PORT}
[root@redis01 ~]# sh redis_shell.sh login 6380
100.1.1.11:6380> CLUSTER MEET 100.1.1.11 6381
OK
100.1.1.11:6380> CLUSTER MEET 100.1.1.12 6380
OK
100.1.1.11:6380> CLUSTER MEET 100.1.1.13 6380
OK
100.1.1.11:6380> CLUSTER MEET 100.1.1.12 6381
OK
100.1.1.11:6380> CLUSTER MEET 100.1.1.13 6381
OK
100.1.1.11:6380> CLUSTER NODES
d03cb38d612802aead8f727b1726a3359c241818 100.1.1.11:6380 myself,master - 0 0 4 connected
67c8128df00b2fa304a41bafbadac25a654f196d 100.1.1.11:6381 master - 0 1562059947079 1 connected
a23ec7d444791a0b258ac454ef15cb4d6ab5abd2 100.1.1.13:6381 master - 0 1562059948087 5 connected
e57807d4d35daaaca05f4a9705e844eab15c7ce8 100.1.1.12:6381 master - 0 1562059949098 0 connected
aa9da67a594dfb357195f12ca4c44001804ee470 100.1.1.13:6380 master - 0 1562059945063 3 connected
5cb6895305520e6a0aa4198a6ea5f2c087530b41 100.1.1.12:6380 master - 0 1562059950108 2 connected
集群模式的Redis除了原有的配置文件之外又加了一份集群配置文件.当集群内节点 信息发生变化,如添加节点,节点下线,故障转移等.节点会自动保存集群状态到配置文件. 需要注意的是,Redis自动维护集群配置文件,不需要手动修改,防止节点重启时产生错乱
在分布式存储中需要提供维护节点元数据信息的机制,所谓元数据是指:节点负责哪些数据,是否出现故障灯状态信息,redis 集群采用 Gossip(流言)协议,Gossip 协议工作原理就是节点彼此不断交换信息,一段时间后所有的节点都会知道集群完整信息,这种方式类似流言传播。 通信过程:
通讯消息类型: Gossip: 协议职责就是信息交换,信息交换的载体就是节点间彼此发送Gossip 消息。 常见 Gossip 消息分为:ping、 pong、 meet、 fail 等 meet 消息:用于通知新节点加入,消息发送者通知接受者加入到当前集群,meet 消息通信正常完成后,接收节点会加入到集群中并进行ping、 pong 消息交换 ping 消息:集群内交换最频繁的消息,集群内每个节点每秒想多个其他节点发送 ping 消息,用于检测节点是否在线和交换彼此信息。 Pong 消息:当接收到 ping,meet 消息时,作为相应消息回复给发送方确认消息正常通信,节点也可以向集群内广播自身的 pong 消息来通知整个集群对自身状态进行更新。 fail 消息:当节点判定集群内另一个节点下线时,回向集群内广播一个fail 消息,其他节点收到 fail 消息之后把对应节点更新为下线状态。
虽然节点之间已经互相发现了,但是此时集群还是不可用的状态,因为并没有给节点分配槽位,而且必须是所有的槽位都分配完毕后整个集群才是可用的状态. 反之,也就是说只要有一个槽位没有分配,那么整个集群就是不可用的.
测试命令:
[root@redis01 ~]# sh redis_shell.sh login 6380
100.1.1.11:6380> set k1 v1
(error) CLUSTERDOWN Hash slot not served
100.1.1.11: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
100.1.1.11:6380>
我们虽然有6个节点,但是真正负责数据写入的只有3个节点,其他3个节点只是作为主节点的从节点,也就是说,只需要分配期中三个节点的槽位就可以了 分配槽位的方法: 分配槽位需要在每个主节点上来配置,此时有2种方法执行:
每个节点执行命令:
[root@redis01 ~]# redis-cli -h redis01 -p 6380 cluster addslots {0..5461}
OK
[root@redis01 ~]# redis-cli -h redis02 -p 6380 cluster addslots {5462..10922}
OK
[root@redis01 ~]# redis-cli -h redis03 -p 6380 cluster addslots {10923..16383}
OK
分配完所有槽位之后我们再查看一下集群的节点状态和集群状态 可以看到三个节点都分配了槽位,而且集群的状态是OK的
虽然这时候集群是可用的了,但是整个集群只要有一台机器坏掉了,那么整个集群都是不可用的. 所以这时候需要用到其他三个节点分别作为现在三个主节点的从节点,以应对集群主节点故障时可以进行自动切换以保证集群持续可用. 注意:
注意: 1.需要执行命令的是每个服务器的从节点 2.注意主从的ID不要搞混了. 执行命令:
[root@redis01 ~]# redis-cli -h redis01 -p 6381 CLUSTER REPLICATE 5cb6895305520e6a0aa4198a6ea5f2c087530b41
OK
[root@redis01 ~]# redis-cli -h redis02 -p 6381 CLUSTER REPLICATE aa9da67a594dfb357195f12ca4c44001804ee470
OK
[root@redis01 ~]# redis-cli -h redis03 -p 6381 CLUSTER REPLICATE d03cb38d612802aead8f727b1726a3359c241818
OK
我们使用常规插入redis数据的方式往集群里写入数据看看会发生什么
[root@redis01 ~]# redis-cli -h redis01 -p 6380 set k1 v1
(error) MOVED 12706 100.1.1.13:6380
结果提示error, 但是给出了集群另一个节点的地址 那么这条数据到底有没有写入呢? 我们登录这两个节点分别查看
[root@redis01 ~]# redis-cli -h redis03 -p 6380 get k1
(nil)
结果没有,这是因为使用集群后由于数据被分片了,所以并不是说在那台机器上写入数据就会在哪台机器的节点上写入,集群的数据写入和读取就涉及到了另外一个概念,ASK路由
在集群模式下,Redis接受任何键相关命令时首先会计算键对应的槽,再根据槽找出所对应的节点 如果节点是自身,则处理键命令; 否则回复MOVED重定向错误,通知客户端请求正确的节点,这个过程称为Mover重定向.
知道了ask路由后,我们使用-c选项批量插入一些数据,会自动跳转到目标节点处理 并且最后由目标节点返回信息
[root@redis01 ~]# cat input_key.sh
#!/bin/bash
for i in $(seq 1 1000)
do
redis-cli -c -h redis01 -p 6380 set k_${i} v_${i} && echo "set k_${i} is ok"
done
写入后我们同样使用-c选项来读取刚才插入的键值,然后查看下redis会不会帮我们路由到正确的节点上
[root@redis01 ~]# redis-cli -c -h redis01 -p 6380
redis01:6380> get k_1
"v_1"
redis01:6380> get k_100
-> Redirected to slot [5541] located at 100.1.1.12:6380
"v_100"
100.1.1.12:6380> get k_1000
-> Redirected to slot [79] located at 100.1.1.11:6380
"v_1000"
100.1.1.11:6380>
至此,我们已经手动的把一个redis高可用的集群部署完毕了, 但是还没有模拟过故障 这里我们就模拟故障,停掉期中一台主机的redis节点,然后查看一下集群的变化 我们使用暴力的kill -9杀掉 redis02上的redis集群节点,然后观察节点状态 理想情况应该是redis01上的6381从节点升级为主节点
在redis01上查看集群节点状态
虽然我们已经测试了故障切换的功能,但是节点修复后还是需要重新上线 所以这里测试节点重新上线后的操作 重新启动redis02的6380,然后观察日志
观察redis01上的日志
这时假如我们想让修复后的节点重新上线,可以在想变成主库的从库执行CLUSTER FAILOVER命令 这里我们在redis02的6380上执行
手动搭建集群便于理解集群创建的流程和细节,不过手动搭建集群需要很多步骤,当集群节点众多时,必然会加大搭建集群的复杂度和运维成本,因此官方提供了 我们可以停掉所有的节点,然后清空数据,恢复成一个全新的集群,所有机器执行命令
pkill redis
rm -rf /data/redis_cluster/redis_6380/*
rm -rf /data/redis_cluster/redis_6381/*
全部清空之后启动所有的节点,所有机器执行
sh redis_shell.sh start 6380
sh redis_shell.sh start 6381
redis01执行创建集群命令
redis-cli create --cluster-replicas 1 100.1.1.11:6380 100.1.1.12:6380 100.1.1.13:6380 100.1.1.11:6381 100.1.1.12:6381 100.1.1.13:6381
检查集群完整性
redis-cli check 100.1.1.11:6380
Redis集群的扩容操作可分为以下几个步骤
我们在redis01上创建2个新节点
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
启动节点
bash redis_shell.sh start 6390
bash redis_shell.sh start 6391
发现节点
redis-cli -c -h redis01 -p 6380 cluster meet 100.1.1.11 6390
redis-cli -c -h redis01 -p 6380 cluster meet 100.1.1.11 6391
在redis01上使用工具扩容
redis-cli reshard 100.1.1.11:6380
打印出进群每个节点信息后,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-cli rebalance 100.1.1.11:6380
流程说明
这里我们准备将刚才新添加的节点下线,也就是6390和6391 收缩和扩容迁移的方向相反,6390变为源节点,其他节点变为目标节点,源节点把自己负责的4096个槽均匀的迁移到其他节点上,. 由于redis-trib..rb reshard命令只能有一个目标节点,因此需要执行3次reshard命令,分别迁移1365,1365,1366个槽. 操作命令:
redis-cli reshard 100.1.1.11:6380
How many slots do you want to move (from 1 to 16384)? 1365
输入6380的id
输入6390的id
done
由于我们的集群是做了高可用的,所以当主节点下线的时候从节点也会顶上,所以最好我们先下线从节点,然后在下线主节点
redis-cli del-node 100.1.1.11:6391 ID
redis-cli del-node 100.1.1.11:6390 ID
集群(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 槽中的键。
[root@redis01 ~]# 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
需求背景 刚切换到redis集群的时候肯定会面临数据导入的问题,所以这里推荐使用redis-migrate-tool工具来导入单节点数据到集群里 官方地址: 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
创建配置文件
[root@redis01 ~]# cat redis_6379_to_6380.conf
[source]
type: single
servers:
- 100.1.1.11:6379
[target]
type: redis cluster
servers:
- 100.1.1.11:6380
[common]
listen: 0.0.0.0:8888
source_safe: true
生成测试数据
[root@redis01 ~]# cat input_key.sh
#!/bin/bash
for i in $(seq 1 1000)
do
redis-cli -c -h redis01 -p 6379 set k_${i} v_${i} && echo "set k_${i} is ok"
done
执行导入命令
[root@redis01 ~]# redis-migrate-tool -c redis_6379_to_6380.conf
数据校验
[root@redis01 ~]# 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 /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
需求背景: 因为开发重复提交,导致商品网站优惠卷过期时间失效 问题分析: 如果一个键已经设置了过期时间,这时候在set这个键,过期时间就会取消 解决思路 如何在不影响机器性能的前提下批量获取需要监控键过期时间
脚本内容:
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 100.1.1.11 -p 6380 SCAN ${key_num} match ${line}\* count 1000|awk 'NR==1{print $0}')
key_name=$(redis-cli -h 100.1.1.11 -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