官方文档:
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