详解Redis主从复制实践


Posted in Redis onMay 19, 2021

复制简介

Redis 作为一门非关系型数据库,其复制功能和关系型数据库(MySQL)来说,功能其实都是差不多,无外乎就是实现的原理不同。Redis 的复制功能也是相对于其他的内存性数据库(memcached)所具备特有的功能。

Redis 复制功能主要的作用,是集群、分片功能实现的基础;同时也是 Redis 实现高可用的一种策略,例如解决单机并发问题、数据安全性等等问题。

服务介绍

在本文环境演示中,有一台主机,启动了两个 Redis 示例。

详解Redis主从复制实践

实现方式

Redis 复制实现方式分为下面三种方式:

1. 服务启动时配置

该方式通过在启动 Redis 服务时,通过命令行参数,进行启动主从复制功能。该方式的弊端是不能实现配置持久化,当服务停掉之后,启动服务时,需要添加相同的命令参数。

1.1 master 服务器事先在 redis.confg 增加 requirepass 项。

requirepass 6379

1.2 启动从服务器。

redis-server --port 6380 --replicaof 192.168.2.102 6379

2. 命令行配置

该方式通过使用 redis-cli 进入操作行界面,进行配置。该方式的弊端是不能实现配置持久化,当服务停掉之后,启动服务需要执行同样的命令。

2.1 master 服务器执行。

127.0.0.1:6379> config set requirepass 6379
OK

2.2 从服务器执行。

127.0.0.1:6380> replicaof 192.168.2.102 6379
OK
127.0.0.1:6380> config set masterauth 6379
OK

3. 配置文件配置

该方式是通过 redis.conf 配置文件进行设置,能够实现配置的持久化,是一种推荐使用的方式。

3.1 配置主服务器,redis.config。

requirepass 6379

3.2 配置从服务器,redis.config。

masterauth 6379
replicaof 192.168.2.102 6379

4.配置说明

1.masterauth:设置 redis.confi 连接密码,如果设置了该值。其他客户端在连接该服务器时,需要添加密码才可以访问。

2.requirepass:设置主服务器的连接密码,和 1 中 masterauth 一致。

3.replicaof:从服务器连接到服务器的 IP 地址+端口号。

效果测试

1.主服务器添加数据

详解Redis主从复制实践

2.从服务器获取数据

详解Redis主从复制实践

实现原理

详解Redis主从复制实践

// uml图

@startuml

从服务器->主服务器: 1.保存配置

从服务器->主服务器: 2.建立socket连接

从服务器->主服务器: 3.发送ping命令

从服务器->主服务器: 4.权限验证

从服务器->主服务器: 5.同步数据

从服务器->主服务器: 6.持续复制数据

@enduml

主从复制主要实现的一个流程如上图:

1.第一步,从服务器保存主服务器的配置信息,保存之后待从服务器内部的定时器执行时,就会触发复制的流程。

2.第二步,从服务器首先会与主服务器建立一个socket套字节连接,用作主从通信使用。后面主服务器发送数据给从服务器也是通过该套字节进行。

3.第三步,socket套字节连接成功之后,接着发送鉴权ping命令,正常的情况下,主服务器会发送对应的响应。ping命令的作用是为了,保证socket套字节是否可以用,同时也是为了验证主服务器是否接受操作命令。

4.第四步,接着就是鉴权验证,判断从节点配置的主节点连接密码是否正确。

5.第五步,鉴权成功之后,就可以开始复制数据了。主服务器此时会进行全量复制,将主服务的数据全部发给从服务器,从服务器保存主服务器发送的数据。

6.接下来就是持续复制操作。主服务器会进行异步复制,一边将写的数据写入自身,同时会将新的写命令发送给从服务器。

实现策略

Redis主从复制主要分为三种弄策略方式,不同的策略方式都是针对不同的场景下进行使用。三种场景方式分别如下:

1.全量复制

全量复制用在主从复制刚建立时或者从切主服务器时,从服务器没有主服务器的数据,主服务器会将自身的数据通过rdb文件方式发送给从服务器,从服务器会清空自身数据,接着将主服务器发送的数据加载到自身中。

详解Redis主从复制实践

// uml图

@startuml

从服务器->主服务器: 1.psync ? -1

主服务器->从服务器: 2.fullsync runid offset

从服务器: 3.保存 runid offset

主服务器: 4.执行bgsave生成rdb

主服务器->从服务器: 5.发送rdb

从服务器: 6.清空自身老数据

从服务器: 7.加载主服务器数据

@enduml

2.部分复制

部分复制用在一些异常情况下,例如主从延迟、从服务宕机之后重新启动接收主服务器发送的部分数据。

部分复制的实现主要依赖于复制缓存区、主服务的runid、主从服务器各自的复制偏移量(offset)。

复制缓存区:主服务在接收写命令时,会将命令写入缓存区,以便从服务器在异常情况下,减少数据的丢失。当从服务器正常连接之后,主服务器会将缓存区内的数据发送给从服务器。这里的缓存区是一个长队列。

主服务器runid:主服务器会在每次服务启动之后,会生成一个唯一的ID,作为自身标识。从服务器会将该标识保存起来,发送部分复制命令时,会使用该runid。

psync runid offset

主从复制各自偏移量:主从服务在建立复制之后,都会有自身的偏移量。从节点会每秒钟发送自身复制的偏移量给从节点,主节点在发送写命令之后,从节点也会增加自身的复制偏移量。主节点在每次进行了写命令之后,也会增加自身的偏移量。这里的偏移量是通过命令的字节长度累加计算。

3.异步复制

异步复制是针对主从建立复制关系之后,主从服务器持续保持复制关系。

场景问题

1.数据安全

// 从服务器只读
replica-read-only yes
// 从服务器连接密码
masterauth

2.数据延迟

默认的情况下主节点存在新数据不会立即发送给从服务器,如果开启,则会理解发送给从服务器。默认的时间拒绝与Linux内核。

// 复制延迟
repl-disable-tcp-nodelay yes

3.主从节点连接状态

主从节点一旦建立连接之后,会定时模拟成对方的客户端,检测对方的服务状态。主节点可以通过设置repl-ping-replica-period配置参数进行设置。默认的频率是10s。

从节点咋执行replconf ack {offsetid}时,也会将自身的复制偏移量发送给主服务器,主服务根据偏移量进行判断数据延迟。存在数据延迟就会从复制积压缓冲区的数据汇中,将对应的数据补发给从节点。

以上就是详解Redis主从复制实践的详细内容,更多关于Redis主从复制实践的资料请关注三水点靠木其它相关文章!

Redis 相关文章推荐
redis 限制内存使用大小的实现
May 08 Redis
Redis数据结构之链表与字典的使用
May 11 Redis
redis实现共同好友的思路详解
May 26 Redis
详解缓存穿透击穿雪崩解决方案
May 28 Redis
详解Redis基本命令与使用场景
Jun 01 Redis
Windows下redis下载、redis安装及使用教程
Jun 02 Redis
解析高可用Redis服务架构分析与搭建方案
Jun 20 Redis
Redis Stream类型的使用详解
Nov 11 Redis
Redis中缓存穿透/击穿/雪崩问题和解决方法
Dec 04 Redis
Redis+Lua脚本实现计数器接口防刷功能(升级版)
Feb 12 Redis
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
Mar 16 Redis
Redis安装使用RedisJSON模块的方法
Mar 23 Redis
详解redis分布式锁的这些坑
为Java项目添加Redis缓存的方法
redis内存空间效率问题的深入探究
深入浅析Redis 集群伸缩原理
Redis延迟队列和分布式延迟队列的简答实现
基于Redis延迟队列的实现代码
基于Redis实现分布式锁的方法(lua脚本版)
You might like
玩家交还《星际争霸》原始码光盘 暴雪报以厚礼
2017/05/05 星际争霸
Wordpress php 分页代码
2009/10/21 PHP
PHP 采集程序原理分析篇
2010/03/05 PHP
解析百度搜索结果link?url=参数分析 (全)
2012/10/09 PHP
分享PHP守护进程类
2015/12/30 PHP
自定义Laravel (monolog)日志位置,并增加请求ID的实现
2019/10/17 PHP
将函数的实际参数转换成数组的方法
2010/01/25 Javascript
JQuery 学习技巧总结
2010/05/21 Javascript
基于jquery的图片幻灯展示源码
2012/07/15 Javascript
JavaScript高级程序设计 阅读笔记(十三) js定义类或对象
2012/08/14 Javascript
关于JavaScript中name的意义冲突示例介绍
2014/05/29 Javascript
JavaScript中使用Object.create()创建对象介绍
2014/12/30 Javascript
Js与Jq 获取页面元素值的方法和差异对比
2015/04/30 Javascript
JQuery中DOM实现事件移除的方法
2015/06/13 Javascript
JS不用正则验证输入的字符串是否为空(包含空格)的实现代码
2016/06/14 Javascript
JavaScript 中Date对象的格式化代码方法汇总
2017/09/06 Javascript
vue-cli之router基本使用方法详解
2017/10/17 Javascript
nodejs中art-template模板语法的引入及冲突解决方案
2017/11/07 NodeJs
在Vue中使用echarts的方法
2018/02/05 Javascript
vue代码分割的实现(codesplit)
2018/11/13 Javascript
详解javascript对数组和json数组的操作
2019/04/15 Javascript
如何提升vue.js中大型数据的性能
2019/06/21 Javascript
[04:09]2018年度DOTA2社区贡献奖-完美盛典
2018/12/16 DOTA
[01:11:21]DOTA2-DPC中国联赛 正赛 VG vs Elephant BO3 第一场 3月6日
2021/03/11 DOTA
python调用接口的4种方式代码实例
2019/11/19 Python
使用pytorch实现可视化中间层的结果
2019/12/30 Python
基于python实现破解滑动验证码过程解析
2020/05/28 Python
Html5游戏开发之乒乓Ping Pong游戏示例(三)
2013/01/21 HTML / CSS
ESDlife健康生活易:身体检查预订、搜寻及比较
2019/05/10 全球购物
Order by的几种用法
2013/06/16 面试题
药学专业个人自我评价
2013/11/11 职场文书
数控机械专业个人的自我评价
2014/01/02 职场文书
董事长助理岗位职责
2014/02/18 职场文书
中国好声音广告词
2014/03/18 职场文书
四风问题党员个人整改措施
2014/10/27 职场文书
教你使用vscode 搭建react-native开发环境
2021/07/07 Javascript