redis的集群模式
redis的集群模式有主从同步,哨兵(sentine),cluster模式,以下是主从同步模式的介绍使用,后续补上其它两种模式
主从同步模式
主从同步也就是读写分离,master主库负责写操作,slave从库负责读操作,slave没有写权限。单机的qps有限,实现主从分布后,请求就分流了,qps就可以提上来,实现水平扩容也容易,直接加从库slave
缺点:
master挂掉,就失去写服务,slave挂了不影响其它slave
原理
全量同步
- slave启动时候,会发送一个psync命令给master,如果是这个从库slave第一次连接,会触发全量复制,复制master上所有数据
- master收到命令,执行bgsave命令,fock子进程生成RDB快照,同时启用缓冲区,把新的写请求写到缓冲区。RDB快照生成后,发送RDB给slave
- slave接收到之后,就写进本地磁盘,然后加载到内存
- master快照发送完毕后,就会把缓冲区新增的写命令以增量同步给slave从库
- slave接收相应的增量指令,加载到内存
增量同步
slave从库初始化完了之后,master的写命令同步到从库的过程即是增量同步。增量复制的过程是master每执行一个写命令就会以AOF形式向slave发送相同的写命令,增量就像MySQL的Binlog一样,把日志增量同步给从服务,slave接收并执行收到的写命令
从库流程
slave连接上master,初始化进行全量同步,初始化完了就进入正常工作,增量同步,保持与master数据一致
配置
测试我用的是一台机子,其中是一个本机windows系统,一个虚拟机centos系统
windows版本:redis-3.2 主库
centos版本:redis-5.0.5 从库
由于版本不同,防止同步时候操作rdb报错,版本选择向前兼容,windows做主库,centos做从库,具体配置内容如下
master配置
G:\>cd redis
放开AOF和设置好aof和rdb存放目录
dir ./
appendonly yes
设置slave从库的连接密码
requirepass 12345
重启redis服务
G:\redis>redis-server
slave配置
# vi /home/tool/redis-5.0.5/redis.conf
放开AOF和设置好aof和rdb存放目录
dir ./
appendonly yes
配置文件新增slave从库配置,格式为 slaveof <master的IP> <redis端口>
slaveof 192.168.XX.XX 6379
设置连接master的密码
masterauth 12345
重启redis服务
# service redis stop
# service redis start
配置完之后,在master查看主从信息,如下图所示,redis是主库,连接进来slave从库一个
在slave查看主从信息,如下图所示,redis是从库,主库ip,端口,已同步偏移量
操作演示
master端
G:\redis>redis-cli
127.0.0.1:6379> auth 12345 #客户端登录,需要密码登录,验证
OK
127.0.0.1:6379> keys *
(empty list or set)
slave启动之后,set值写入,slave端查看
127.0.0.1:6379> set username toegg
OK
127.0.0.1:6379> keys *
1) "username"
这个时候slave断开后,等slave重启服务连入之后,set值写入,slave端查看
127.0.0.1:6379> set age 18
OK
关闭master的服务,执行代码验证,失去了写服务,slave端读取正常
127.0.0.1:6379> SHUTDOWN
not connected> QUIT
重启master服务
G:\redis>redis-server
127.0.0.1:6379> auth 12345 #客户端登录,需要密码登录,验证
OK
127.0.0.1:6379> keys *
1) "username"
2) "age"
slave端
[root@localhost /]# redis-cli
127.0.0.1:6379> keys *
(empty list or set)
写入,因为从库只能读,提示写入失败
127.0.0.1:6379> set username toegg
(error) READONLY You can't write against a read only replica.
主库写完,slave查看
127.0.0.1:6379> keys *
1) "username"
127.0.0.1:6379> get username
"toegg"
重启服务,重新连接主库,同时数据加载进内存
127.0.0.1:6379> SHUTDOWN
not connected> QUIT
[root@localhost /]# service redis start
Starting Redis server...
16658:C 28 May 2020 12:40:04.327 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
16658:C 28 May 2020 12:40:04.328 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=16658, just started
16658:C 28 May 2020 12:40:04.328 # Configuration loaded
[root@localhost /]# redis-cli
127.0.0.1:6379> keys *
1) "username"
127.0.0.1:6379> get username
"toegg"
重启服务后,主库端再写入,slave再查看
127.0.0.1:6379> keys *
1) "age"
2) "username"
127.0.0.1:6379> get age
"18"
127.0.0.1:6379> keys *
1) "age"
2) "username"
代码层,用在关闭master服务后验证时执行。这里注意写入要连接到master端,读取则是连接到slave端,实际生产,要根据请求去做相应分发到不同连接端处理业务逻辑。本例只是简单列出相对应测试代码,如下:
//master写服务验证
$master = new Redis();
try{
$master->connect('192.168.XX.XX', 6379);
$master->auth("12345"); #auth验证
$result = $master->keys('*');
echo "master keys :"; print_r($result);
$master->set("work", "docker");
$result = $master->keys('*');
echo "master keys :"; print_r($result);
}catch(Exception $exc){
echo "写服务失效";
}
//slave写服务验证
$slave = new Redis();
try{
$slave->connect('127.0.0.1', 6379);
$result = $slave->keys('*');
echo "slave keys :"; print_r($result);
}catch(Exception $exec){
echo "读服务失效";
}
操作步骤如下:
-
slave写入,因为从库只能读,提示写入失败
-
master写入,slave查看,已同步到slave
-
重启slave,会重新连接master并加载主库的数据
-
slave重启后,master再写入,slave查看,会同步到slave
-
关闭master,执行代码验证,失去了master写服务,slave从库能继续读取,验证如图
-
重启master,执行代码验证,写服务恢复,读服务也正常,验证如图
总结:
- master主库负责写,slave从库负责读
- slave首次连接进行初始化,异步和master进行全量同步,同步主库所有数据,初始化完后,master以AOF形式执行增量同步到slave
- master挂了,失去写服务,从库正常读取
- slave重启,会重新连接master,进入之后的增量同步工作
以上就是主从同步的相关内容和使用,有错误的地方,请大家指点。测试用的是本机和虚拟机,只有一主一从,实际投产根据实际去调控水平扩容