Redis主从复制
概述
一般来说,要将Redis运用于工程项目中,只使用一台Redis是万万不能的,原因如下:
- 从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大;
- 从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内容容量为256G,也不能将所有内容用作Redis存储内存,一般来说,单台Redis最大使用内存不应该超过20G。
本文先讨论第一点的解决方案:Redis主从复制,第二点可以使用Redis集群解决,下一篇文章将介绍Redis集群。
主从复制
考虑如下一种场景:
电子商务网站上的商品,一般都是一次上传,无数次浏览的,说专业点也就是”多读少写”。
如图中所示,我们将一台Redis服务器作主库(Matser),其他三台作为从库(Slave),主库只负责写数据,每次有数据更新都将更新的数据同步到它所有的从库,而从库只负责读数据。这样一来,就有了两个好处:
- 读写分离,不仅可以提高服务器的负载能力,并且可以根据读请求的规模自由增加或者减少从库的数量,棒极了;
- 数据被复制成了了好几份,就算有一台机器出现故障,也可以使用其他机器的数据快速恢复。
需要注意的是:在Redis主从模式中,一台主库可以拥有多个从库,但是一个从库只能隶属于一个主库。
配置
在Redis中,要实现主从复制架构非常简单,只需要在从数据库的配置文件中加上如下命令即可:
1
| slaveof 主数据库地址 主数据库端口
|
主数据库不需要任何配置。
示例
下面将演示怎么实现一个简单的复制系统。我们在一台机器上起两个Redis实例,监听不同的端口,其中一个作为主库,另外一个作为从库。首先不加任何参数来启动一个Redis实例作为主数据库:
可以看到,主库监听的是6379端口。
然后加上slaveof参数启动另一个Redis实例作为从库,并且监听6380端口:
从控制台输出中可以看到,从库已经连接到主库:126.0.0.1:6379了,看样子主从复制系统配置成功。我们可以分别在主库和从库中使用如下命令看一看当前实例在复制系统中的相关信息:
接下来验证一把。
首先在主库中设置一个键值:
1 2 3 4 | [qifuguang@Mac~]$ /opt/soft/redis-3.0.4/src/redis-cli -p 6379 127.0.0.1:6379> set test-sync winwill2012 OK 127.0.0.1:6379> |
现在到从库中检查该值是否已经自动同步到了从库:
1 2 3 4 | [qifuguang@Mac~]$ /opt/soft/redis-3.0.4/src/redis-cli -p 6380 127.0.0.1:6380> get test-sync "winwill2012" 127.0.0.1:6380> |
可以看到,数据确实从主库同步到了从库.
在默认情况下,从库是只读的,如果在从库中写数据将会报错:
1 2 3 4 | [qifuguang@Mac~]$ /opt/soft/redis-3.0.4/src/redis-cli -p 6380 127.0.0.1:6380> set x y (error) READONLY You can't write against a read only slave. 127.0.0.1:6380> |
但是可以在从库的配置文件中加上如下的配置项允许从库写数据:
1
| slave-read-only no
|
但是,因为从库中修改的数据不会被同步到任何其他数据库,并且一旦主库修改了数据,从库的数据就会因为自动同步被覆盖,所以一般情况下,不建议将从库设置为可写。
相同的道理,配置多台从库也使用相同的方法,都在从库的配置文件中加上slaveof参数即可。
此外,我们可以在客户端使用命令
1
| SLAVEOF 新主库地址 新主库端口
|
来修改当前数据库的主库,如果当前数据库已经是其他库的从库, 则当前数据库会停止和原来的数据库的同步而和新的数据库同步。
最后,从数据库还可以通过运行命令:
1
| SLAVEOF NO ONE
|
来停止接受来自其他数据库的同步而升级成为主库。
原理
上面说了配置主从复制系统的方法,并且举例例子详细说明,本节将介绍Redis主从复制的实现原理。
当一个从数据库启动时,会向主数据库发送SYNC命令,主数据库收到命令后会开始在后台保存快照(即RDB持久化过程),并将保存快照期间接收到的命令缓存起来。当快照完成后,Redis会将快照文件和缓存的命令发给从数据库,从数据库收到数据后,会载入快照文件并执行缓存的命令。以上过程称为复制初始化。复制初始化之结束后,主数据库每收到写命令时就会将命令同步给从数据库,从而保证主从数据库数据一致,这一过程称为复制同步阶段。
有两点需要注意:
- 当主从数据库之间的连接断开后,Redis2.8之前的版本会重新进行复制初始化过程,这样就使得主从数据库断开连接后数据恢复的过程的效率很低下。Redis2.8版本的一个重要改进就是断线支持有条件的增量数据传输,当从数据库再次连接到主数据库时,主数据库只需要将断线期间执行的命令发给从数据库即可,大大提高了Redis主从复制的实用性。
- 复制同步阶段贯穿整个主从同步过程的始终,直到主从关系终止为止。在复制过程中,即使关闭了RDB方式的持久化(删除所有save参数),依旧会执行快照操作。
乐观复制
Redis采用了复制的策略。容忍在一定时间内主从数据库的内容是不同的,但是两者的数据最终会保持一致。具体来说,Redis主从数据库之间的复制数据的过程本身是异步的,这意味着,主数据库执行完客户端的写请求后会立即将命令在主数据库的执行结果返回给客户端,而不会等待从数据库收到该命令后再返回给客户端。这一特性保证了复制后主从数据库的性能不会受到影响,但另一方面也会产生一个主从数据库数据不一致的时间窗口,当主数据库执行一条写命令之后,主数据库的数据已经发生变动,然而在主数据库将该命令传送给从数据库之前,如果两个数据库之间的连接断开了,此时二者间的数据就不一致了。从这个角度看,主数据库无法得知命令最终同步给了几个从数据库,不过Redis提供了两个配置选项来限制只有至少同步给指定数量的数据库时,主数据库才是可写的:
1 2 | min-slaves-to-write 3 min-slave2-max-lag 10 |
第一个参数表示只有当3个或3个以上的从数据库连接到主库时,主数据库才是可写的,否则返回错误。
第二个参数表示允许从数据库失去连接的最长时间,该选项默认是关闭的,在分布式系统中,打开并合理配置该选项可以降低主从架构因为网络分区导致的数据不一致问题。
图结构
从数据库不仅可以接收主数据库的数据,同时也可以作为主数据库存在,形成类似图的结构,如下图:
A中的数据会同步到B,C中,C中的数据会同步到D,E中。
-
-
u013043341
2017-08-31 21:30 4楼 -
学习到了,谢谢博主分享,多多加油!
-
-
-
-
zyt425916200
2017-08-06 23:46 3楼 -
感谢分享
-
-
-
-
Y8806662681
2017-07-28 16:37 2楼 -
你好,那客户端读取数据是怎么读取的呢?
1 主机与从机读写分离,那么如果主机数据修改了还没同步到从机,这个时候去从机读到的数据不就有问题了么?
2 如果有多台从机,主机往从机写数据也会有先后顺序吧。比如A,B,C三台从机,当主机把数据写到从机A时,客户端读到了从机C的数据怎么办? -
-
-
-
u013034640
2017-05-03 12:49 1楼 -
很详细的总结,学习了。
-
-
Redis主从复制和集群配置
- u011204847
- 2016年05月03日 19:58
- 38665
Redis源码解析:17Resis主从复制之主节点的部分重同步流程及其他
- gqtcgq
- 2016年04月30日 17:31
- 3025
Redis主从复制实现
- why_2012_gogo
- 2016年05月17日 15:36
- 1321
redis的主从复制配置
- yangzhenzhen
- 2013年01月17日 10:29
- 39915
Redis实现主从复制(Master&Slave)
- zhangguanghui002
- 2017年11月13日 21:06
- 537
Redis集群之主从复制,读写分离(上)(五)
- cuipeng0916
- 2016年12月17日 10:18
- 4642
Redis学习笔记五:redis主从复制
- lijunxian1013
- 2016年07月22日 13:59
- 3130
Redis主从复制
- zouyujie1127
- 2014年11月23日 15:18
- 6726
Redis 主从复制
- qq_19558705
- 2017年11月30日 22:14
- 314
Redis研究(十二)—主从复制
- wtyvhreal
- 2015年01月21日 21:25
- 2913
Redis主从复制总结整理
- imxiangzi
- 2016年09月01日 16:25
- 420
redis主从复制和集群实现原理
- nuli888
- 2016年08月06日 16:17
- 12235
Redis源码解析:15Resis主从复制之从节点流程
- gqtcgq
- 2016年04月17日 10:43
- 3397
redis主从复制及切换
- xiaoyu_0217
- 2017年07月17日 18:39
- 403
redis的主从复制(读写分离)/哨兵(主从切换)配置
- zmx729618
- 2017年08月04日 14:04
- 1229
Redis主从架构和主从从架构集群搭建详细步骤
- RobertoHuang
- 2017年04月25日 20:08
- 2164
Redis集群 - 配置最简单的Redis主从
- github_26672553
- 2017年04月08日 10:57
- 987
redis主从配置及主从切换
- zfl092005
- 2013年12月24日 10:00
- 61936
Redis 主从配置心得及其高可用方案
- Quiet_boy
- 2016年12月26日 13:29
- 4601
Redis学习笔记(三) Redis主从架构和主从从架构 (1)
- a67474506
- 2015年12月30日 16:12
- 6927
-
原创
- 16
-
粉丝
- 126
-
喜欢
- 7
-
评论
- 74
他的最新文章
更多文章文章分类
- 微信
13篇
- 云计算
1篇
- python
2篇
- Java
25篇
- MongoDB
8篇
- Spring
3篇
- Linux
4篇
- JavaScript
2篇
- ext
1篇
- mysql
6篇
- Redis
6篇
- tomcat
1篇
- Git
1篇
- Nginx
5篇
- Socket
3篇
文章存档
- 2017年11月
1篇
- 2017年4月
1篇
- 2017年3月
1篇
- 2016年12月
3篇
- 2016年8月
1篇
- 2016年7月
2篇
- 2016年6月
2篇
- 2016年4月
9篇
- 2016年3月
4篇
- 2016年1月
3篇
- 2015年11月
2篇
- 2015年10月
17篇
- 2015年9月
2篇
- 2015年8月
3篇
- 2015年7月
11篇
- 2015年5月
2篇
- 2014年3月
16篇
他的热门文章
- Mysql字符串字段判断是否包含某个字符串的3种方法
77542
- Redis五种数据类型介绍
30201
- 微信公共服务平台开发(.Net 的实现)5-------解决access_token过期的问题
23797
- Redis事务介绍
20183
- 17784
- 微信公共服务平台开发(.Net 的实现)8-------处理图片(上传下载发送)
16311
- Linux下如何搭建VPN服务器
12412
- 微信公共服务平台开发(.Net 的实现)6-------自定义菜单
11946
- Redis主从复制
11177
- Java 动态生成jpg图片
11081