欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Redis -- 13 -- Redis主从同步搭建

程序员文章站 2024-03-20 21:40:34
...

相关文章:


官方文档:Replication


Redis 主从同步是指将一台 Redis 服务器上的数据,同步到另一台或多台 Redis 服务器上,前者称为主节点 (Master),后者称为从节点 (Slave);一个主节点可以有多个从节点 (也可以没有),而一个从节点只能有一个主节点


一、Redis 主从同步介绍

  • Redis 默认使用异步复制,其特点是低延迟和高性能,是绝大多数 Redis 实例的自然复制模式,也就是说 Slave 会异步地确认从 Master 周期性接收到的数据

  • 主从同步的运行依靠以下三个主要机制

    • 当 Master 和 Slave 连接正常时,Master 会向 Slave 发送命令流来使 Slave 保持更新,以便将自身发生的数据集改变复制给 Slave,包括:客户端的写入、Key 的过期或删除或其他任何更改 Master 数据集的操作

    • 当 Master 和 Slave 连接断开后,Slave 重新连接上 Master 时,会尝试对断开期间内丢失的命令流进行同步 (部分同步)

    • 当无法进行部分同步时,Slave 会尝试进行全量同步,Master 会创建一个所有数据的快照,将其发送给 Slave,之后在数据集更改时,持续发送命令流到 Slave

  • 主从同步作用

    • 数据冗余

      • 主从同步实现了数据的热备份,是持久化之外的一种数据冗余方式
    • 故障恢复

      • 当 Master 发生故障时,可以由 Slave 提供服务,实现了快速的故障恢复
    • 读写分离

      • Master 负责写操作,Slave 负责读操作,缓解了 Master 的读写压力,大大提高了数据库的读写性能

二、Redis 主从同步原理

  • 每个 Master 都有一个 replication ID (复制 ID,这是一个较大的伪随机字符串,标记了一个给定的数据集)

  • 每个 Master 都持有一个 offset (偏移量),Master 将自身产生的复制流发送给 Slave,发送多少个字节的数据,自身 offset 就会增加多少,目的是当有新的操作修改自身数据集时,Master 可以以此来更新 Slave 的状态

  • 即使没有一个 Slave 连接到 Master,offset 也会增加,也就是说每一对给定的 replication ID 和 offset 都会标识一个 Master 数据集的确切版本


三、Redis 主从同步过程

  • 增量同步

    • Slave 使用 PSYNC 命令发送其记录的旧的 replication ID 和至今为止处理的 offset 到 Master

    • Master 接收到 PSYNC 命令后,只需要发送 Slave 所需的增量部分即可

      • 如果 Master 的积压缓冲区不足,或 Slave 引用的 replication ID 不可知,则会转换为全量同步,在这种情况下,Slave 会得到一个完整的数据集副本
  • 全量同步

    • Slave 发送 PSYNC 命令到 Master

    • Master 启动一个后台进程,将 Redis 中的数据快照保存到 RDB 文件中 (即 bgsave 操作)

    • Master 会将保存快照期间接收到的写命令缓存起来 (即将增量数据缓存起来)

    • Master 在完成写文件 (RDB 文件) 的操作后,会将 RDB 文件发送给 Slave

    • Salve 接收到文件后,会将文件保存到磁盘上,然后将文件加载到内存中去恢复数据快照

    • 当 Slave 完成数据快照的恢复后,Master 会将此期间收集到的增量写命令发送给 Slave 进行恢复


四、Redis 主从配置参数

  • replicaof <masterip> <masterport>

    • 设置 Master IP + 端口号
  • masterauth <master-password>

    • 设置 Master 密码

五、Redis 如何开启主从同步

  • 修改配置文件

    • 修改 Slave 配置文件 replicaof <masterip> <masterport>

    • 如果 Master 有密码,则还需要修改 masterauth <master-password>

  • 使用启动命令

    • 使用 redis-server 命令启动时,加入 --replicaof <masterip> <masterport> 参数
  • 使用客户端命令

    • 当 Redis 服务启动后,通过 redis-cli 进入客户端执行命令 replicaof <masterip> <masterport>

六、搭建 Redis 主从同步

  • 1、在服务器上搭建一个单机版的 Redis,具体流程参考 --> Redis – 02 – Linux上源码包安装Redis

  • 2、在 /usr/local/ 目录下新建 redis-master-slave 目录,用于存放主 Slave

    • cd /usr/local/

    • mkdir redis-master-slave

  • 3、将第 1 步安装完的 Redis 的 bin 目录下的所有文件复制到 /usr/local/redis-master-slave/redis01/ 目录下

    • cp -r /usr/local/redis/bin/ /usr/local/redis-master-slave/redis01/
  • 4、修改 /usr/local/redis-master-slave/redis01/ 目录下的 redis.conf 配置文件

    • vim /usr/local/redis-master-slave/redis01/redis.conf

      # 将 bind 127.0.0.1 一行注释掉
      # bind 127.0.0.1
      
      # 设置端口
      port 6386
      
      # 开启守护进程
      daemonize yes
      
      # 设置 pid 文件
      pidfile /var/run/redis-6386.pid
      
      # 设置 log 文件
      logfile "./redis-6386.log"
      
      # 设置工作目录
      dir ./
      
      # 设置 Master 密码
      masterauth 123456
      
      # 设置密码
      requirepass 123456
      
    • :wq

  • 5、在 /usr/local/redis-master-slave/redis01/ 目录下编写启动脚本

    • vim /usr/local/redis-master-slave/redis01/start.sh

      #!/bin/bash
      
      #实例路径
      APP_NAME=/usr/local/redis-master-slave/redis01/redis-server
      #配置文件路径
      APP_CONF=/usr/local/redis-master-slave/redis01/redis.conf
      
      #使用说明,用来提示输入参数
      usage() {
      	echo "Usage: run.sh {start|stop|restart|status}"
      	exit 1
      }
      
      #检查程序是否正在运行
      is_running() {
      	pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}'`
      	#如果不存在则返回1,存在则返回0
      	if [ -z "${pid}" ];
      	then
      		return 1
      	else
      		return 0
      	fi
      }
      
      #启动
      start() {
      	is_running
      	if [ $? -eq 0 ];
      	then
      		echo "${APP_NAME} is already running, pid=${pid}"
      	else
      		${APP_NAME} ${APP_CONF}
      	fi
      }
      
      #停止
      stop() {
      	is_running
      	if [ $? -eq 0 ];
      	then
      		kill -9 $pid
      	else
      		echo "${APP_NAME} is not running"
      	fi
      }
      
      #查看运行状态
      status() {
      	is_running
      	if [ $? -eq 0 ];
      	then
      		echo "${APP_NAME} is running, pid is ${pid}"
      	else
      		echo "${APP_NAME} is not running"
      	fi
      }
      
      #重启
      restart() {
      	stop
      	sleep 5
      	start
      }
      
      #根据输入的参数,选择对应的执行方法,不输入则执行使用说明
      case "$1" in
      	start)
      		start
      		;;
      	stop)
      		stop
      		;;
      	status)
      		status
      		;;
      	restart)
      		restart
      		;;
      	*)
      		usage
      		;;
      esac
      
    • :wq

    • chmod +x /usr/local/redis-master-slave/redis01/start.sh

  • 6、将 /usr/local/redis-master-slave/redis01/ 目录下的所有文件复制 2 份到 /usr/local/redis-master-slave/(redis02 - redis03)/ 目录下

    • cp -r /usr/local/redis-master-slave/redis01/ /usr/local/redis-master-slave/redis02/

    • cp -r /usr/local/redis-master-slave/redis01/ /usr/local/redis-master-slave/redis03/

    • 在 redis02 - redis03 两个文件中,修改 redis.conf 配置文件和 start.sh 启动脚本

      • redis.conf 配置文件

        • port 分别改为 6387 - 6388

        • pidfile 分别改为 /var/run/redis-(6387 - 6388).pid;

        • logfile 分别改为 ./redis-(6387 - 6388).log

        • 除此之外,还需要更改以下配置

          # 设置 Master IP + 端口号 (用于主从同步)
          replicaof 127.0.0.1 6386
          
      • start.sh 启动脚本

        • redis01 分别改为 redis02 - redis03
      • 其中 redis01 作为主节点 (Master),redis02、redis03 作为从节点 (Slave)

  • 7、在 /usr/local/redis-master-slave/ 目录下编写总的启动脚本和总的关闭脚本

    • vim /usr/local/redis-master-slave/start.sh

      #!/bin/bash
      
      #项目路径
      REDIS01_PATH=/usr/local/redis-master-slave/redis01
      REDIS02_PATH=/usr/local/redis-master-slave/redis02
      REDIS03_PATH=/usr/local/redis-master-slave/redis03
      
      #使用说明,用来提示输入参数
      usage() {
      	echo "Usage: start.sh {all|redis01|redis02|redis03}"
      	exit 1
      }
      
      #启动所有
      all() {
      	cd ${REDIS01_PATH}
      	./start.sh start
      
      	cd ${REDIS02_PATH}
      	./start.sh start
      	
      	cd ${REDIS03_PATH}
      	./start.sh start
      }
      
      #启动redis01
      redis01() {
      	cd ${REDIS01_PATH}
      	./start.sh start
      }
      
      #启动redis02
      redis02() {
      	cd ${REDIS02_PATH}
      	./start.sh start
      }
      
      #启动redis03
      redis03() {
      	cd ${REDIS03_PATH}
      	./start.sh start
      }
      
      #根据输入的参数,选择对应的执行方法,不输入则执行使用说明
      case "$1" in
      	all)
      		all
      		;;
      	redis01)
      		redis01
      		;;
      	redis02)
      		redis02
      		;;
      	redis03)
      		redis03
      		;;
      	*)
      		usage
      		;;
      esac
      
    • :wq

    • chmod +x /usr/local/redis-master-slave/start.sh

    • vim /usr/local/redis-master-slave/stop.sh

      #!/bin/bash
      
      #项目路径
      REDIS01_PATH=/usr/local/redis-master-slave/redis01
      REDIS02_PATH=/usr/local/redis-master-slave/redis02
      REDIS03_PATH=/usr/local/redis-master-slave/redis03
      
      #使用说明,用来提示输入参数
      usage() {
      	echo "Usage: stop.sh {all|redis01|redis02|redis03}"
      	exit 1
      }
      
      #关闭所有
      all() {
      	cd ${REDIS01_PATH}
      	./start.sh stop
      
      	cd ${REDIS02_PATH}
      	./start.sh stop
      	
      	cd ${REDIS03_PATH}
      	./start.sh stop
      }
      
      #关闭redis01
      redis01() {
      	cd ${REDIS01_PATH}
      	./start.sh stop
      }
      
      #关闭redis02
      redis02() {
      	cd ${REDIS02_PATH}
      	./start.sh stop
      }
      
      #关闭redis03
      redis03() {
      	cd ${REDIS03_PATH}
      	./start.sh stop
      }
      
      #根据输入的参数,选择对应的执行方法,不输入则执行使用说明
      case "$1" in
      	all)
      		all
      		;;
      	redis01)
      		redis01
      		;;
      	redis02)
      		redis02
      		;;
      	redis03)
      		redis03
      		;;
      	*)
      		usage
      		;;
      esac
      
    • :wq

    • chmod +x /usr/local/redis-master-slave/stop.sh

  • 8、启动所有 Redis 实例

    • /usr/local/redis-master-slave/start.sh all
  • 9、查看 Reids 实例进程

    • ps -ef | grep redis

      Redis -- 13 -- Redis主从同步搭建

  • 10、将第 1 步安装完的 Redis 的 bin 目录下的 redis-cli 文件复制到 /usr/local/redis-master-slave/ 目录下

    • cp /usr/local/redis/bin/redis-cli /usr/local/redis-master-slave/
  • 11、查看节点主从情况

    • /usr/local/redis-master-slave/redis-cli -a 123456 -p 6386

      Redis -- 13 -- Redis主从同步搭建

    • /usr/local/redis-master-slave/redis-cli -a 123456 -p 6387

      Redis -- 13 -- Redis主从同步搭建

    • /usr/local/redis-master-slave/redis-cli -a 123456 -p 6388

      Redis -- 13 -- Redis主从同步搭建

  • 12、至此,Redis 主从同步就搭建成功了


七、Redis 主从同步测试

  • Master 测试

    • 连接 Redis 集群 Master

      • /usr/local/redis-master-slave/redis-cli -a 123456 -p 6386
    • 进行测试

      Redis -- 13 -- Redis主从同步搭建

    • 测试结果

      Redis -- 13 -- Redis主从同步搭建

    • 由测试结果可知,在 Master 中写入数据会自动同步到 Slave

  • Slave 测试

    • 连接 Redis 集群 Slave

      • /usr/local/redis-master-slave/redis-cli -a 123456 -p 6387
    • 进行测试

      Redis -- 13 -- Redis主从同步搭建

    • 测试结果

      • 由测试结果可知,在 Slave 中无法写入数据

八、参考资料

相关标签: Redis Master-Slave