redis的集群模式之主从模式(五)

redis的集群模式

redis的集群模式有主从同步,哨兵(sentine),cluster模式,以下是主从同步模式的介绍使用,后续补上其它两种模式


主从同步模式

主从同步也就是读写分离,master主库负责写操作,slave从库负责读操作,slave没有写权限。单机的qps有限,实现主从分布后,请求就分流了,qps就可以提上来,实现水平扩容也容易,直接加从库slave

缺点:
master挂掉,就失去写服务,slave挂了不影响其它slave

原理

全量同步

  1. slave启动时候,会发送一个psync命令给master,如果是这个从库slave第一次连接,会触发全量复制,复制master上所有数据
  2. master收到命令,执行bgsave命令,fock子进程生成RDB快照,同时启用缓冲区,把新的写请求写到缓冲区。RDB快照生成后,发送RDB给slave
  3. slave接收到之后,就写进本地磁盘,然后加载到内存
  4. master快照发送完毕后,就会把缓冲区新增的写命令以增量同步给slave从库
  5. 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 "读服务失效";
}

操作步骤如下:

  1. slave写入,因为从库只能读,提示写入失败

  2. master写入,slave查看,已同步到slave

  3. 重启slave,会重新连接master并加载主库的数据

  4. slave重启后,master再写入,slave查看,会同步到slave

  5. 关闭master,执行代码验证,失去了master写服务,slave从库能继续读取,验证如图
    代码执行图

  6. 重启master,执行代码验证,写服务恢复,读服务也正常,验证如图
    代码执行图2


总结:

  1. master主库负责写,slave从库负责读
  2. slave首次连接进行初始化,异步和master进行全量同步,同步主库所有数据,初始化完后,master以AOF形式执行增量同步到slave
  3. master挂了,失去写服务,从库正常读取
  4. slave重启,会重新连接master,进入之后的增量同步工作

以上就是主从同步的相关内容和使用,有错误的地方,请大家指点。测试用的是本机和虚拟机,只有一主一从,实际投产根据实际去调控水平扩容

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章