主从模式(master-slave)
实战
规划图
实际配置
1,克隆主机,以redis1为基础,克隆出redis2和3
2,配置IP和主机名称,重启,使用xshell链接
vi /etc/sysconfig/network-scripts/ifcfg-ens33
:15 21->22
vi /etc/hostname
:1 redis2
reboot 重启
使用xshell或者finalShell 链接
redis 3同上
3,配置主从
不能使用vim的,使用下列命令:
yum -y install vim
master:
cp /usr/redis/redis-5.0.5/redis.conf /usr/redis/bin/master.conf
vim /usr/redis/bin/master.conf
:set nu
:69 bind 本地IP(192.168.xxx.21)
:92 port 6666
:136 daemonize yes
slave1:
cp /usr/redis/redis-5.0.5/redis.conf /usr/redis/bin/slave1.conf
vim /usr/redis/bin/slave1.conf
:set nu
:69 bind 本地IP(192.168.xxx.22)
:92 port 7777
:136 daemonize yes
在文件末尾添加如下配置(大写G):
#主从配置
slaveof 192.168.170.21 6666
slave2:
cp /usr/redis/redis-5.0.5/redis.conf /usr/redis/bin/slave2.conf
vim /usr/redis/bin/slave2.conf
:set nu
:69 bind 本地IP(192.168.xxx.23)
:92 port 8888
:136 daemonize yes
#主从配置
slaveof 192.168.170.21 6666
测试
启动服务端:
master:
/usr/redis/bin/redis-server /usr/redis/bin/master.conf
slave1:
/usr/redis/bin/redis-server /usr/redis/bin/slave1.conf
slave2:
/usr/redis/bin/redis-server /usr/redis/bin/slave2.conf
在allsession查看是否启动成功:
ps -ef|grep redis-server|grep -v grep
测试主从:
master:
/usr/redis/bin/redis-cli -h 192.168.170.21 -p 6666
>keys *
>flushall
>keys *
> set a 1
>mset b 2 c 3
#在redis3宕机的时候
>mset aa 11 bb 22 cc 33
slave1:
/usr/redis/bin/redis-cli -h 192.168.170.22 -p 7777
>keys *
>keys *
>keys *
> set aa 11
(error) READONLY You can't write against a read only replica. 你不能在一个只读的副本上进行写操作
>keys * 正常看到aa bb cc
slave2:
/usr/redis/bin/redis-cli -h 192.168.170.23 -p 8888
>keys *
>keys *
>keys *
> set aa 11
(error) READONLY You can't write against a read only replica. 你不能在一个只读的副本上进行写操作
/usr/redis/bin/redis-cli -h 192.168.170.23 -p 8888 shutdown 关闭redis服务端
再次启动redis3:
/usr/redis/bin/redis-server /usr/redis/bin/slave2.conf
客户端链接:
/usr/redis/bin/redis-cli -h 192.168.170.23 -p 8888
>keys* 发现存在aa bb cc
原理
哨兵模式(sentinel)
实战
规划图
实战配置
master:
cp /usr/redis/redis-5.0.5/sentinel.conf /usr/redis/bin/s1.conf
vim /usr/redis/bin/s1.conf
#关闭保护模式 当开启保护模式的时候默认只能本机连
protected-mode no #17
#哨兵端口
port 26666 #21 port 27777 port 28888
#添加守护进程模式
daemonize yes #26
#添加指明日志文件名
logfile "./temp.log" #36
#修改工作目录
dir "/tmp" #65
#哨兵监控的master名称可以随便起,ip和端口固定 quorum 当哨兵是集群时,有多少个哨兵认为master失效(客观下线),master才算失效。 防止脑裂 配置计算最好是 哨兵总数量/2+1
sentinel monitor mymaster 192.168.170.31 6666 2 #84
#设置master和slaves验证密码
sentinel auth-pass mymaster 123456 #103
#master(默认30秒)不能使用后标记为主观down状态。
sentinel down-after-milliseconds mymaster 30000 #113
slave1:
cp /usr/redis/redis-5.0.5/sentinel.conf /usr/redis/bin/s2.conf
slave2:
cp /usr/redis/redis-5.0.5/sentinel.conf /usr/redis/bin/s3.conf
测试
master:
/usr/redis/bin/redis-sentinel /usr/redis/bin/s1.conf
slave1:
/usr/redis/bin/redis-sentinel /usr/redis/bin/s2.conf
slave2:
/usr/redis/bin/redis-sentinel /usr/redis/bin/s3.conf
在allsesion中查看是否启动成功:
ps -ef|grep redis|grep -v grep
能看到 26666 27777 28888 和三个对应redis实例,都在运行。
再次查看主从:
/usr/redis/bin/redis-cli -h 192.168.170.21 -p 6666
> info replication
分别在redis1,2,3执行命令,查看当前redis节点的角色
能看出来redis1是master 2,3是slave
让redis1宕机,等30秒。
/usr/redis/bin/redis-cli -h 192.168.170.21 -p 6666 shutdown
发现redis2变为master
在新master的redis2执行写操作:
192.168.170.22:7777> keys *
1) "c"
2) "bb"
3) "b"
4) "aa"
5) "d"
6) "cc"
7) "a"
192.168.170.22:7777> mset aaa 111 bbb 222 ccc 333
OK
192.168.170.22:7777> lpush lista 11 22 33 44
(integer) 4
192.168.170.22:7777> keys *
1) "lista"
2) "c"
3) "ccc"
4) "aa"
5) "aaa"
6) "d"
7) "b"
8) "bb"
9) "a"
10) "cc"
11) "bbb"
发现redis3都有了
再次启动redis1的redis实例,发现自动变为slave
>keys * 发现宕机时master写的数据,已经同步了
原理
特点
高可用(除了主节点宕机,选举出新的主节点之前,集群不可用,其他时间都是高可用的)
哨兵在监控所有的redis节点
自动故障迁移(切换)(master宕机,自动选举slave做master)
缺点
自动故障切换时集群不可用
master依然存在写压力
集群(cluster)
作用
引言
在web项目中,为了提高访问效率,通常会把热点数据(经常被访问的数据)不从数据直接获取,而是放入nosql框架中(基于内存)。web网站一般遵循28定律,80%访问量往往集中在20%的业务上。大型网站20%的业务产生的热点往往巨大。单个redis存在容量瓶颈(单机的内存有限),所以要使用集群,让更多redis存储数据。
高可用高可用
不存在单点故障。(基于主从做的,主节点宕机,从节点自动变为主节点)
高性能
集群中的每一个节点的性能和单机版完全一样
方便扩展
动态添加或者缩减节点
master写负载均衡
不再是一个主节点写,多个主节点进行写负载均衡(同时写)
实战
规划图
实战配置
在allsession:
mdkir /usr/redis/cluster
分别在redis1,2,3
mkdir /usr/redis/cluster/8001 /usr/redis/cluster/8002
mkdir /usr/redis/cluster/8003 /usr/redis/cluster/8004
mkdir /usr/redis/cluster/8005 /usr/redis/cluster/8006
在allsession:
ls /usr/redis/cluster
在redis1,复制redis.conf到8001下:
cp /usr/redis/redis-5.0.5/redis.conf /usr/redis/cluster/8001/
修改配置文件:
vim /usr/redis/cluster/8001/redis.conf
参考配置详情
复制8001的配置,修改:
cp /usr/redis/cluster/8001/redis.conf /usr/redis/cluster/8002/
远程复制配置好的文件:
scp /usr/redis/cluster/8001/redis.conf 192.168.170.22:/usr/redis/cluster/8003/
scp /usr/redis/cluster/8001/redis.conf 192.168.170.22:/usr/redis/cluster/8004/
scp /usr/redis/cluster/8001/redis.conf 192.168.170.23:/usr/redis/cluster/8005/
scp /usr/redis/cluster/8001/redis.conf 192.168.170.23:/usr/redis/cluster/8006/
修改文件:
修改IP和端口,可以使用批量修改
vim /usr/redis/cluster/8002/redis.conf
:%s/8001/8002/g
vim /usr/redis/cluster/8003/redis.conf
:69 21->22
:%s/8001/8003/g
vim /usr/redis/cluster/8004/redis.conf
:69 21->22
:%s/8001/8004/g
vim /usr/redis/cluster/8005/redis.conf
:69 21->23
:%s/8001/8005/g
vim /usr/redis/cluster/8006/redis.conf
:69 21->23
:%s/8001/8006/g
配置详情
/关键字 //例如 /port 在文件中查找port
bind 本机ip //默认ip为127.0.0.1 需要改为其他节点机器可访问的ip 否则创建集群时无法访问对应的端口,无法创建集群 69行
port 6001 //端口7001,7002,7003 92行
daemonize yes //redis后台运行 136行
pidfile /var/run/redis_6001.pid //pidfile文件对应7000,7001,7002 158行
appendonly yes //aof日志开启 有需要就开启,它会每次写操作都记录一条日志 699行
appendfilename "appendonly-6001.aof" //AOF 持久化使用的文件名称 703行
cluster-enabled yes //开启集群 把注释#去掉 832行
cluster-config-file nodes_6001.conf //集群的配置 配置文件首次启动自动生成 7000,7001,7002 840行
cluster-node-timeout 15000 //请求超时 默认15秒,可自行设置 846行
scp ssh 及免密原理
scp
在网络中的不同主机上复制文件或者目录
ssh
登录一个远程服务器并执行命令
原理
测试
概述
redis集群搭建,需要6个节点都启动起来,并且创建集群(只创建一次),以后集群的启动,就是6个节点的启动,集群的关闭就是6个节点的关闭!
启动6个节点:
/usr/redis/bin/redis-server /usr/redis/cluster/8001/redis.conf
/usr/redis/bin/redis-server /usr/redis/cluster/8002/redis.conf
/usr/redis/bin/redis-server /usr/redis/cluster/8003/redis.conf
/usr/redis/bin/redis-server /usr/redis/cluster/8004/redis.conf
/usr/redis/bin/redis-server /usr/redis/cluster/8005/redis.conf
/usr/redis/bin/redis-server /usr/redis/cluster/8006/redis.conf
查看是否启动成功:
ps -ef|grep redis-server|grep -v grep
创建集群:
启动或者关闭脚本
编辑文件:
vim shelldir/redis-start-stop.sh
复制下面内容:
#!/bin/bash
#获取当前服务器运行的进程数量
rpsnum=`ps -ef |grep redis-server|grep -v grep|wc -l`
#判断rpsnum是否为0
if [ $rpsnum == 0 ];then
#启动redis集群
#打印提示
echo 'redis集群开始启动......'
ssh 192.168.170.21 "/usr/redis/bin/redis-server /usr/redis/cluster/8001/redis.conf"
ssh 192.168.170.21 "/usr/redis/bin/redis-server /usr/redis/cluster/8002/redis.conf"
ssh 192.168.170.22 "/usr/redis/bin/redis-server /usr/redis/cluster/8003/redis.conf"
ssh 192.168.170.22 "/usr/redis/bin/redis-server /usr/redis/cluster/8004/redis.conf"
ssh 192.168.170.23 "/usr/redis/bin/redis-server /usr/redis/cluster/8005/redis.conf"
ssh 192.168.170.23 "/usr/redis/bin/redis-server /usr/redis/cluster/8006/redis.conf"
echo 'redis集群启动完成......'
else
#关闭redis集群
#打印提示
echo 'redis集群开始关闭......'
ssh 192.168.170.21 "/usr/redis/bin/redis-cli -h 192.168.170.21 -p 8001 shutdown"
ssh 192.168.170.21 "/usr/redis/bin/redis-cli -h 192.168.170.21 -p 8002 shutdown"
ssh 192.168.170.22 "/usr/redis/bin/redis-cli -h 192.168.170.22 -p 8003 shutdown"
ssh 192.168.170.22 "/usr/redis/bin/redis-cli -h 192.168.170.22 -p 8004 shutdown"
ssh 192.168.170.23 "/usr/redis/bin/redis-cli -h 192.168.170.23 -p 8005 shutdown"
ssh 192.168.170.23 "/usr/redis/bin/redis-cli -h 192.168.170.23 -p 8006 shutdown"
echo 'redis集群关闭完成......'
fi
修改权限
chmod +x redis-start-stop.sh
使用:
./shelldir/redis-start-stop.sh
原理
节点-槽-值的关系
在redis集群模式下,不再使用过去默认16个库来存储数据,而是使用16384个槽slot来存储数据。
节点和操作的关系:
槽会被平均分配到master节点上。
节点 槽 数量
8001 0-5460 5461
8003 5461-10922 5462
8005 10923-16383 5461
值和槽的关系:
redis所有数据类型都有key,并且key是唯一的,redis底层就会使用CRC16算法,可以根据key计算得到一个唯一的数字,使用数字对16384取余,余数为几就放入到该槽中。
值 计算 槽 槽范围 节点
aaa=111 crc16('aaa')%16384 10439 5461-10922 8003
bbb=222 crc16('bbb')%16384 5287 0-5460 8001
ddd=444 crc16('ddd')%16384 11367 10923-16383 8005
集群实现细节
架构图
具体细节
1,所有节点都是相互联通,底层用的ping-pong机制。
2,某一个节点宕机,不是一个节点说了算,而是集群中超过半数的节点都连不上,才说明真正宕机(超过半数计算=节点总数量/2+1)
3,客户端链接集群时,不用连接每一个节点,而是连接任意节点都可以
4,每个节点除了保存自身数据之外,还保存了整个集群的状态
.......
自动故障切换
创建集群时,使用参数--cluster-replicas=1 一个主节点对应一个从节点,这样做保证数据的高可用,当主节点宕机,自动切换从节点为主节点(默认为15秒,可以修改),宕机主节点再恢复,自动变为从节点。
使用cluster nodes可知:
主 从
8001 8004
8003 8006
8005 8002
让8001或者8003或者8005任意一个宕机
让8001宕机:
/usr/redis/bin/redis-cli -h 192.168.170.21 -p 8001 shutdown
等15秒后,再使用cluster nodes:
再次链接:
/usr/redis/bin/redis-cli -h 192.168.170.21 -p 8002 -c
cluster nodes
看到8004变为master
再次启动8001:
/usr/redis/bin/redis-server /usr/redis/cluster/8001/redis.conf
再次链接:
/usr/redis/bin/redis-cli -h 192.168.170.21 -p 8002 -c
再使用cluster nodes:
发现8001变为slave
主 从
8004 8001
8003 8006
8005 8002
集群失败的原因
没有从节点的主节点宕机,集群就变为失败状态
现在状态:
主 从
8004 8001
8003 8006
8005 8002
先把8006宕机:
/usr/redis/bin/redis-cli -h 192.168.170.23 -p 8006 shutdown
使用cluster nodes 和cluster info,观察8006处于失败状态,但是整个集群正常,这个时候8003就没有从节点。
再把没有从节点的8003宕机:
/usr/redis/bin/redis-cli -h 192.168.170.22 -p 8003 shutdown
等待15秒:
cluster info
整个集群失败,也可以看到哪些槽正常,哪些槽失败!
超过半数的主节点同时(不能超过15秒)宕机
现在状态:
主 从
8004 8001
8003 8006
8005 8002
超过半数=总数量/2+1
从上面观察让8003和8004同时宕机:
/usr/redis/bin/redis-cli -h 192.168.170.22 -p 8003 shutdown
/usr/redis/bin/redis-cli -h 192.168.170.22 -p 8004 shutdown
15秒后:
cluster info
整个集群失败,也可以看到哪些槽正常,哪些槽失败!
特点
1、无中心架构(不存在哪个节点影响性能瓶颈),少了 proxy(代理) 层。
2、数据按照 slot 存储分布在多个节点,节点间数据共享,可动态调整数据分布。
3、可扩展性,可线性扩展到 1000 个节点,节点可动态添加或删除。
假如1000个节点 16384 一个节点上只放 16.4 槽 数据更均匀的存放不同的服务器,假如该服务器的内存全用来缓存,能缓存的数据会更多
4、高可用性,部分节点不可用时,集群仍可用。通过增加 Slave 做备份数据副本
5、实现故障自动 failover(容错),节点之间通过 gossip 协议交换状态信息,用投票机制完成 Slave到 Master 的角色提升。
Gossip (疫情传播算法)过程是由种子节点发起,当一个种子节点有状态需要更新到网络中的其他节点时,它会随机的选择周围几个节点散播消息,收到消息的节点也会重复该过程,直至最终网络中所有的节点都收到了消息。
缺点
1、资源隔离性较差,容易出现相互影响的情况(多个应用同时使用一个redis集群时,可能会出现)。
2、数据通过异步复制,不保证数据的强一致性
3、自动故障切换时,集群状态fail 无法对外提供服务