1.前言

说到分布式高可用,必然少不了复制,一来是为了做个冗余备份防止数据丢失,二来还可以达到分流来提高性能的目的。基本架构:

下面用M表示Master(主服务器),S表示Slave(从服务器),话不多说,先敲代码

2.配置

slaveof 192.168.1.1 6379

在S端配置slaveof就可以实现复制了,意思是我从192.168.1.1 6379这台M复制数据。注意第一次复制的时候S上面的数据会被覆盖。下面就在我的虚拟机上面实操一下,配置3台redis,6379是M,6380、6381是S

配置M

$ cp redis.conf redis_6379.conf
$ vi redis_6379.conf
bind 192.168.56.10 #修改ip为本机

配置S

$ cp redis_6379.conf redis_6380.conf
$ vi redis_6380.conf
#修改端口号和pid文件名
port 6380
pidfile /var/run/redis_6380.pid
slaveof 192.168.56.10 6379 #设定复制
#同样拷贝一份配置按照上面的步骤修改6381的配置
$ cp redis_6380.conf redis_6381.conf

启动

$ src/redis-server redis_6379.conf
$ src/redis-server redis_6380.conf
$ src/redis-server redis_6381.conf

测试复制

$ src/redis-cli -h 192.168.56.10 -p 6379
192.168.56.10:6379> set name pigfly
OK
192.168.56.10:6379> quit
$ src/redis-cli -h 192.168.56.10 -p 6380
192.168.56.10:6380> get name
"pigfly" #复制成功
192.168.56.10:6380> quit
$ src/redis-cli -h 192.168.56.10 -p 6379
192.168.56.10:6379> del name
(integer) 1
192.168.56.10:6379> quit
$ src/redis-cli -h 192.168.56.10 -p 6380
192.168.56.10:6380> get name
(nil) #删除同步成功192.168.56.10:6380> set age 23
#注意S只读,这是默认配置,如果要S可写修改read-only=no#一般来说不建议这样做,因为复制的时候会把数据覆盖
(error) READONLY You can't write against a read only slave.192.168.56.10:6380> quit
$ src/redis-cli -h 192.168.56.10 -p 6379
192.168.56.10:6379> setex address 10 xxstreat
OK
192.168.56.10:6379> quit
$ src/redis-cli -h 192.168.56.10 -p 6380
192.168.56.10:6380> get address
(nil) #过期同步成功

3.原理

当M和S连接正常时,redis通过命令传播来同步数据,每当M执行一个写命令,就会把命令发送给S,S执行后,两者达到数据的一致性。当S第一次连接或者断线后重连M的时候,复制过程是这样子的:

这个过程也可以称作是sync全量复制,每一次复制,M执行bgsave把所有数据打包成快照文件发给S,S再解包载入内存。

M执行bgsave消耗CPU、内存、磁盘I/O,传输过程消耗网络带宽,如果S是第一次连接M,不可避免会执行上述操作,但如果S是断线重连的情况,就有点不划算了,因为S真正需要复制的数据是断线以后的,如果全量复制就太浪费资源和时间了,所以redis2.8以后的版本做了改进,加了psync增量复制,psync(part-sync)跟sync不同的是,psync只发送S真正需要的命令流,大大地提高了打包和传输的效率,那么redis是怎么实现增量复制的呢?

replid, offset

每个M和S都有上面这两个属性,replid是M的唯一标识。offset是命令流的字节数,简单来说,只要有写入命令(就算没有S),这个offset就会增加

M维护着上图这样一个固定长度、先进先出的队列来保存最近的命令流

上图就是增量复制的过程,假定S当前offset=offset_s,M当前offset=offset_m:

1.M判断replid是否和自己的replid相等,如果不相等,跳出执行全量复制

2.M检查offset_s是否还在缓冲队列,如果是,发送从offset_s开始到offset_m的命令流,如果没有了,跳出执行全量复制

3.S执行命令流,更新offset_s = offset_m

复制的机制和特点:

  • 当M和S连接良好时,S定时请求M进行复制,M向S发送命令流来保持同步
  • redis默认使用高性能的异步复制,S会异步向M确认收到的数据
  • 当M和S由于网络问题或者超时导致断开连接,S会尝试重新连接,请求增量复制
  • 不能增量复制时,执行全量复制
  • 一个M可以有多个S
  • S也可以复制其他S
  • 复制在M端是非阻塞的,也就是M向S复制的过程中,M的查询不受影响
  • 复制在S端也基本上是非阻塞的,初始化同步的时候,S可以提供旧数据来使查询不受影响,载入数据的时候,S将会阻塞连接不提供查询服务(非常大的数据也只需要短短几秒就同步完了),旧数据将会被删除,新数据将会被载入
  • 可以把耗时查询放到S上面来提高主机的性能
  • 可以使用复制来避免M持久化带来的开销,让一个S来持久化,但是应该避免M重启,因为M重启之后数据是空的,这时候如果同步的话S的数据也变成空了。就算是用redis的sentinel实现的高可用方案,也不要把持久化关了,说不定sentinel还没来得及检测到故障,M就已经宕机然后重启了。为了避免这种情况,建议M和S都打开持久化,下面就演示数据是如何丢失的:
    • A,B,C三台redis服务器,A是M,B和C是S
    • 因为某些原因,A宕机了,它执行自动重启机制,这时候因为关闭了持久化,磁盘里是没有备份数据的,内存里的数据也因为重启丢失了,所以重启之后数据全部丢了
    • B和C尝试同步,它们也不管A的数据是不是空,照常同步过来了,所以B和C的数据也丢了

redis复制如何处理过期的缓存?

  1. S不处理,而是等M处理过期后给S发送DEL命令
  2. 当M没有及时发送DEL命令,导致过期的缓存仍然存在于S,S将会根据自己的逻辑时钟报告缓存已过期,并且设置为只读
  3. Lua脚本运行的时候,不执行缓存回收
  4. 一旦S变身为M,它马上自个儿执行缓存回收

使用Docker和NAT的情况,如何配置?

使用端口转发和网络地址转换的时候,redis复制要特别小心,特别是使用redis-sentiner,它是根据INFO命令来获取IP地址的,这种情况下可以配置IP端口映射,来让M获取到S正确的地址:

slave-announce-ip 5.5.5.5
slave-announce-port 1234

  

这样M执行INFO命令看到S的IP就是映射过的:

# Replication
role:master
connected_slaves:1
slave0:ip=5.5.5.5,port=1234,state=online,offset=420,lag=1

  

INFO命令

通过info命令可以查看复制的参数和状态

$ src/redis-cli -h 192.168.56.10 -p 6381
192.168.56.10:6381> info
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.56.10,port=6379,state=online,offset=644,lag=1
master_replid:b01608293384f8ea87b5bd0aabe081948f33a3dd
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:644
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:644

  

4.性能优化

1.调整缓冲队列的大小来尽可能达到增量复制而避免全量复制,repl-backlog-size默认1mb

5.参考资料

redis文档

redis实战

redis设计与实现

转载于:https://www.cnblogs.com/justlikeheaven/p/7799224.html

redis复制原理和应用相关推荐

  1. 深入理解redis复制原理

    深入理解redis复制原理 1.复制过程 2.数据间的同步 3.全量复制 4.部分复制 5.心跳 6.异步复制 1.复制过程 从节点执行 slaveof 命令. 从节点只是保存了 slaveof 命令 ...

  2. java redis 重连_突破Java面试(23-4) - Redis 复制原理

    全是干货的技术号: 本文已收录在github,欢迎 star/fork: 在Redis复制的基础上(不包括Redis Cluster或Redis Sentinel作为附加层提供的高可用功能),使用和配 ...

  3. 2021年了,Redis复制原理你应该理解!

    作者:JingQ https://www.sevenyuan.cn/ Redis的单机模式不难,配置文件参数了解具体含义,设定业务上符合自己的就好了. 之前记录了关于Redis的数据结构和对象的知识( ...

  4. redis主从复制原理、断点续传、无磁盘化复制、过期key处理

    1.主从架构的核心原理: 当启动一个salve node时会发送PSYNC 命令到master. salve第一次连接master时master会根据当前数据复制一份RDB(full resynchr ...

  5. 复制给节点的命令_深入理解redis主从复制原理

    1.复制过程 从节点执行 slaveof 命令. 从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制. 从节点内部的定时任务发现有主节点的信息,开始使用 socket 连接主节点 ...

  6. Redis 复制、Sentinel的搭建和原理说明(转)

    Redis 复制.Sentinel的搭建和原理说明 转自:http://www.cnblogs.com/zhoujinyi/p/5570024.html. 背景: Redis-Sentinel是Red ...

  7. Redis入门完整教程:复制原理

    6.3.1 复制过程 在从节点执行slaveof命令后,复制过程便开始运作,下面详细介绍建立 复制的完整流程,如图6-7所示. 从图中可以看出复制过程大致分为6个过程: 1)保存主节点(master) ...

  8. Redis复制(Replication)

    Redis复制(Replication) 本文档翻译自: http://redis.io/topics/replication . Redis 支持简单且易用的主从复制(master-slave re ...

  9. 深入Redis 主从复制原理

    复制原理 1.复制过程 复制的过程步骤如下: 1.从节点执行 slaveof 命令        2.从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制        3.从节点 ...

最新文章

  1. UC浏览器代理流量解密
  2. Fastadmin笔记
  3. python简单发音-Python如何实现文本转语音
  4. LeetCode 55. 跳跃游戏 中等难度
  5. 黑龙江大学计算机考研专业课,2017考研:计算机科学与技术专业考研院校推荐之黑龙江大学...
  6. 批量关闭公众号推送_微信内测新功能:可批量关闭订阅号推送
  7. 多个线程对串口读取 modbus_看完这个,如果还不懂Modbus,那您去撞豆腐吧
  8. html div 监听事件无效,在AngularJS中将html替换为div后,Click事件不起作用
  9. 自定义binder架构的 client/ server组件
  10. swagger连接mysql数据库_一键生成数据库文档,堪称数据库界的Swagger,有点厉害!...
  11. 【渝粤题库】广东开放大学 管理会计 形成性考核
  12. CoinFLEX的基本情况以及与Bakkt
  13. 百度SEO标题关键词伪原创组合工具
  14. APKTOOL反编译使用教程
  15. mysql分页查询非常慢_MySQL分页查询慢的原因及解决方案
  16. RegShot(注册表比较工具)v2.0.1.68绿色中文版
  17. 《GPU编程与CG语言之阳春白雪下里巴人》阅读笔记 第三章+第四章
  18. 性能测试---搬运自Performance Testing Guidance for Web Applications,作者J.D. Meier, Carlos Farre, Prashant Ban
  19. 积累的VC编程小技巧之打印相关
  20. 外贸新手如何利用领英寻找你的潜在客户(建议收藏)

热门文章

  1. oracle菜鸟学习之 复杂的更新语句使用
  2. 计算机组成原理笔记第十章笔记整理
  3. Android动态添加Device Admin权限
  4. LINUX 第六章 Open WebMail完全安装手册
  5. 字符串、列表、元组、字典
  6. python学习方法_十二种学习Python的方法
  7. endless admin_一次中国之旅如何激发Endless OS并教孩子们黑客
  8. aspell_如何使用Aspell在Linux命令行上检查拼写
  9. nginx mozilla_如何开始为Mozilla贡献力量
  10. eff java_牛津大学为国家图书馆周开幕,EFF组织大学活动家,等等