赞
踩
官方文档:
https://redis.io/topics/persistence
- 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默认开启了保护模式,只允许本地回环地址登录并访问数据库
禁止protected-mode
protected-mode yes/no (保护模式,是否只允许本地访问)
- 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的基础,后面的哨兵和集群都是在复制的基础上实现高可用的.
- 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 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器
Sentinel 节点是一个特殊的 Redis 节点,他们有自己专属的 API(端口)
- 哨兵是基于主从复制,所以需要先部署好主从复制
- 手工操作步骤如下:
- 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地址
- 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
当所有节点启动后,配置文件的内容发生了变化,体现在三个方面:
- 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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。