Redis复制流程概述
Redis的复制功能是完全建树在之前我们评论辩论过的基于内存快照的持久化策略根蒂根基上的,也就是说无论你的持久化策略选择的是什么,只要用到了Redis的复制功能,就必然会有内存快照产生,那么起首要重视你的体系内存容量规划,原因可以参考我上一篇文章中提到的Redis磁盘IO题目。
Redis复制流程在Slave和Master端各自是一套状况机流转,涉及的状况信息是:
Slave 端:
REDIS_REPL_NONE
REDIS_REPL_CONNECT
REDIS_REPL_CONNECTED
Master端:
REDIS_REPL_WAIT_BGSAVE_START
REDIS_REPL_WAIT_BGSAVE_END
REDIS_REPL_SEND_BULK
REDIS_REPL_ONLINE
全部状况机流程过程如下:
- Slave端在设备文件中添加了slave of指令,于是Slave启动时读取设备文件,初始状况为REDIS_REPL_CONNECT。
- Slave端在按时任务serverCron(Redis内部的按时器触发事务)中连接Master,发送sync号令,然后梗阻守候master发送回其内存快照文件(最新版的Redis已经不须要让Slave梗阻)。
- Master端收到sync号令简单断定是否有正在进行的内存快照子过程,没有则立即开端内存快照,有则守候其停止,当快照完成后会将该文件发送给Slave端。
- Slave端接管Master发来的内存快照文件,保存到本地,待接管完成后,清空内存表,从头读取Master发来的内存快照文件,重建全部内存表数据布局,并终极状况置位为 REDIS_REPL_CONNECTED状况,Slave状况机流转完成。
- Master端在发送快照文件过程中,接管的任何会改变数据集的号令都邑临时先保存在Slave收集连接的发送缓存队列里(list数据布局),待快照完成后,依次发给Slave,之后收到的号令雷同处理惩罚,并将状况置位为 REDIS_REPL_ONLINE。
全部复制过程完成,流程如下图所示:
Redis复制机制的缺点
从上方的流程可以看出,Slave从库在连接Master主库时,Master会进行内存快照,然后把全部快照文件发给Slave,也就是没有象MySQL那样有复制地位的概念,即无增量复制,这会给全部集群搭建带来很是多的题目。
比如一台线上正在运行的Master主库设备了一台从库进行简单读写分别,这时Slave因为收集或者其它原因与Master断开了连接,那么当Slave进行从头连接时,须要从头获取全部Master的内存快照,Slave所稀有据跟着全部清除,然后从头建树全部内存表,一方面Slave恢复的时候会很是慢,另一方面也会给主库带来压力。
所以基于上述原因,若是你的Redis集群须要主从复制,那么最功德先设备好所有的从库,避免半途再去增长从库。
Cache还是Storage
在我们解析过了Redis的复制与持久化功能后,我们不可贵出一个结论,实际上Redis今朝公布的版本还都是一个单机版的思路,首要的题目集中在,持久化体式格式不敷成熟,复制机制存在斗劲大的缺点,这时我们又开端从头思虑Redis的定位:Cache还是Storage?
若是作为Cache的话,似乎除了有些很是特别的营业场景,必必要应用Redis的某种数据布局之外,我们应用Memcached可能更合适,毕竟成果Memcached无论客户端包和办事器本身更久经考验。
若是是作为存储Storage的话,我们面对的最大的题目是无论是持久化还是复制都没有办法解决Redis单点题目,即一台Redis挂掉了,没有太好的办法可以或许快速的恢复,凡是几十G的持久化数据,Redis重启加载须要几个小时的时候,而复制又出缺点,如何解决呢?
Redis可扩大集群搭建
1. 主动复制避开Redis复制缺点。
既然Redis的复制功能出缺点,那么我们不妨放弃Redis本身供给的复制功能,我们可以采取主动复制的体式格式来搭建我们的集群景象。
所谓主动复制是指由营业端或者经由过程****代理中心件对Redis存储的数据进行双写或多写,经由过程数据的多份存储来达到与复制雷同的目标,主动复制不仅限于用在Redis集群上,今朝很多公司采取主动复制的技巧来解决MySQL主从之间复制的延迟题目,比如Twitter还专门开辟了用于复制和分区的中心件gizzard(https://github.com/twitter/gizzard) 。
主动复制固然解决了被动复制的延迟题目,但也带来了新的题目,就是数据的一致性题目,数据写2次或多次,如何包管多份数据的一致性呢?若是你的应用对数据一致性请求不高,容许终极一致性的话,那么凡是简单的解决规划是可以经由过程时代戳或者vector clock等体式格式,让客户端同时取到多份数据并进行校验,若是你的应用对数据一致性请求很是高,那么就须要引入一些错杂的一致性算法比如Paxos来包管数据的一致性,然则写入机能也会响应降落很多。
经由过程主动复制,数据多份存储我们也就不再愁闷Redis单点故障的题目了,若是一组Redis集群挂掉,我们可以让营业快速切换到另一组Redis上,降落营业风险。
2. 经由过程presharding进行Redis在线扩容。
经由过程主动复制我们解决了Redis单点故障题目,那么还有一个首要的题目须要解决:容量规划与在线扩容题目。
我们前面解析过Redis的实用处景是全部数据存储在内存中,而内存容量有限,那么起首须要按照营业数据量进行初步的容量规划,比如你的营业数据须要100G存储空间,假设办事器内存是48G,那么按照上一篇我们评论辩论的Redis磁盘IO的题目,我们大约须要3~4台办事器来存储。这个实际是对现有营业景象所做的一个容量规划,假如营业增长很快,很快就会发明当前的容量已经不敷了,Redis里面存储的数据很快就会跨越物理内存大小,那么如何进行Redis的在线扩容呢?
Redis的作者提出了一种叫做presharding的规划来解决动态扩容和数据分区的题目,实际就是在同一台机械上安排多个Redis实例的体式格式,当容量不敷时将多个实例拆分到不合的机械上,如许实际就达到了扩容的结果。
拆分过程如下:
- 在新机械上启动好对应端口的Redis实例。
- 设备新端口为待迁徙端口的从库。
- 待复制完成,与主库完成同步后,切换所有客户端设备到新的从库的端口。
- 设备从库为新的主库。
- 移除老的端话柄例。
- 反复上述过程迁徙好所有的端口到指定办事器上。
以上拆分流程是Redis作者提出的一个腻滑迁徙的过程,不过该拆分办法还是很依附Redis本身的复制功能的,若是主库快照数据文件过大,这个复制的过程也会好久,同时会给主库带来压力。所以做这个拆分的过程最好选择为营业接见低峰时段进行。
Redis复制的改进思路
我们线上的体系应用了我们本身改进版的Redis,首要解决了Redis没有增量复制的缺点,可以或许完成类似Mysql Binlog那样可以经由过程从库恳求日记地位进行增量复制。
我们的持久化规划是起首写Redis的AOF文件,并对这个AOF文件按文件大小进行主动分别迁移转变,同时封闭Redis的Rewrite号令,然后会在营业低峰时候进行内存快照存储,并把当前的AOF文件地位一路写入到快照文件中,如许我们可以使快照文件与AOF文件的地位对峙一致性,如许我们获得了体系某一时刻的内存快照,并且同时也能知道这一时刻对应的AOF文件的地位,那么当从库发送同步号令时,我们起首会把快照文件发送给从库,然后从库会取出该快照文件中存储的AOF文件地位,并将该地位发给主库,主库会随后发送该地位之后的所有号令,今后的复制就都是这个地位之后的增量信息了。
Redis与MySQL的连络
今朝大项目组互联网公司应用MySQL作为数据的首要持久化存储,那么如何让Redis与MySQL很好的连络在一路呢?我们首要应用了一种基于MySQL作为主库,Redis作为高速数据查询从库的异构读写分别的规划。
为此我们专门开辟了本身的MySQL复制对象,可以便利的及时同步MySQL中的数据到Redis上。
(MySQL-Redis 异构读写分别)
总结:
- Redis的复制功能没有增量复制,每次重连都邑把主库全部内存快照发给从库,所以须要避免向在线办事的压力较大的主库上增长从库。
- Redis的复制因为会应用快照持久化体式格式,所以若是你的Redis持久化体式格式选择的是日记追加体式格式(aof),那么体系有可能在同一时刻既做aof日记文件的同步刷写磁盘,又做快照写磁盘操纵,这个时辰Redis的响应才能会受到影响。所以若是选用aof持久化,则加从库须要加倍谨慎。
- 可以应用主动复制和presharding办法进行Redis集群搭建与在线扩容。
本文加上之前的2篇文章根蒂根基将Redis的最常用功能和应用处景与优化进行了解析和评论辩论,实际Redis还有很多其它帮助的一些功能,Redis的作者也在络续测验测验新的思路,这里就不一一列举了,有爱好的伴侣可以研究下,也很迎接一路评论辩论