redis复制原理和应用
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复制如何处理过期的缓存?
- S不处理,而是等M处理过期后给S发送DEL命令
- 当M没有及时发送DEL命令,导致过期的缓存仍然存在于S,S将会根据自己的逻辑时钟报告缓存已过期,并且设置为只读
- Lua脚本运行的时候,不执行缓存回收
- 一旦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复制原理和应用相关推荐
- 深入理解redis复制原理
深入理解redis复制原理 1.复制过程 2.数据间的同步 3.全量复制 4.部分复制 5.心跳 6.异步复制 1.复制过程 从节点执行 slaveof 命令. 从节点只是保存了 slaveof 命令 ...
- java redis 重连_突破Java面试(23-4) - Redis 复制原理
全是干货的技术号: 本文已收录在github,欢迎 star/fork: 在Redis复制的基础上(不包括Redis Cluster或Redis Sentinel作为附加层提供的高可用功能),使用和配 ...
- 2021年了,Redis复制原理你应该理解!
作者:JingQ https://www.sevenyuan.cn/ Redis的单机模式不难,配置文件参数了解具体含义,设定业务上符合自己的就好了. 之前记录了关于Redis的数据结构和对象的知识( ...
- redis主从复制原理、断点续传、无磁盘化复制、过期key处理
1.主从架构的核心原理: 当启动一个salve node时会发送PSYNC 命令到master. salve第一次连接master时master会根据当前数据复制一份RDB(full resynchr ...
- 复制给节点的命令_深入理解redis主从复制原理
1.复制过程 从节点执行 slaveof 命令. 从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制. 从节点内部的定时任务发现有主节点的信息,开始使用 socket 连接主节点 ...
- Redis 复制、Sentinel的搭建和原理说明(转)
Redis 复制.Sentinel的搭建和原理说明 转自:http://www.cnblogs.com/zhoujinyi/p/5570024.html. 背景: Redis-Sentinel是Red ...
- Redis入门完整教程:复制原理
6.3.1 复制过程 在从节点执行slaveof命令后,复制过程便开始运作,下面详细介绍建立 复制的完整流程,如图6-7所示. 从图中可以看出复制过程大致分为6个过程: 1)保存主节点(master) ...
- Redis复制(Replication)
Redis复制(Replication) 本文档翻译自: http://redis.io/topics/replication . Redis 支持简单且易用的主从复制(master-slave re ...
- 深入Redis 主从复制原理
复制原理 1.复制过程 复制的过程步骤如下: 1.从节点执行 slaveof 命令 2.从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制 3.从节点 ...
最新文章
- UC浏览器代理流量解密
- Fastadmin笔记
- python简单发音-Python如何实现文本转语音
- LeetCode 55. 跳跃游戏 中等难度
- 黑龙江大学计算机考研专业课,2017考研:计算机科学与技术专业考研院校推荐之黑龙江大学...
- 批量关闭公众号推送_微信内测新功能:可批量关闭订阅号推送
- 多个线程对串口读取 modbus_看完这个,如果还不懂Modbus,那您去撞豆腐吧
- html div 监听事件无效,在AngularJS中将html替换为div后,Click事件不起作用
- 自定义binder架构的 client/ server组件
- swagger连接mysql数据库_一键生成数据库文档,堪称数据库界的Swagger,有点厉害!...
- 【渝粤题库】广东开放大学 管理会计 形成性考核
- CoinFLEX的基本情况以及与Bakkt
- 百度SEO标题关键词伪原创组合工具
- APKTOOL反编译使用教程
- mysql分页查询非常慢_MySQL分页查询慢的原因及解决方案
- RegShot(注册表比较工具)v2.0.1.68绿色中文版
- 《GPU编程与CG语言之阳春白雪下里巴人》阅读笔记 第三章+第四章
- 性能测试---搬运自Performance Testing Guidance for Web Applications,作者J.D. Meier, Carlos Farre, Prashant Ban
- 积累的VC编程小技巧之打印相关
- 外贸新手如何利用领英寻找你的潜在客户(建议收藏)
热门文章
- oracle菜鸟学习之 复杂的更新语句使用
- 计算机组成原理笔记第十章笔记整理
- Android动态添加Device Admin权限
- LINUX 第六章 Open WebMail完全安装手册
- 字符串、列表、元组、字典
- python学习方法_十二种学习Python的方法
- endless admin_一次中国之旅如何激发Endless OS并教孩子们黑客
- aspell_如何使用Aspell在Linux命令行上检查拼写
- nginx mozilla_如何开始为Mozilla贡献力量
- eff java_牛津大学为国家图书馆周开幕,EFF组织大学活动家,等等