前言web
在上一篇文章中,介绍了Redis的内存模型,从这篇文章开始,将依次介绍Redis高可用相关的知识——持久化、复制(及读写分离)、哨兵、以及集群。redis
本文将先说明上述几种技术分别解决了Redis高可用的什么问题;而后详细介绍Redis的持久化技术,主要是RDB和AOF两种持久化方案;在介绍RDB和AOF方案时,不只介绍其做用及操做方法,同时介绍持久化实现的一些原理细节及须要注意的问题。最后,介绍在实际使用中,持久化方案的选择,以及常常遇到的问题等。数据库
1、Redis高可用概述安全
在介绍Redis高可用以前,先说明一下在Redis的语境中高可用的含义。服务器
咱们知道,在web服务器中,高可用是指服务器能够正常访问的时间,衡量的标准是在多长时间内能够提供正常服务(99.9%、99.99%、99.999% 等等)。可是在Redis语境中,高可用的含义彷佛要宽泛一些,除了保证提供正常服务(如主从分离、快速容灾技术),还须要考虑数据容量的扩展、数据安全不会丢失等。负载均衡
在Redis中,实现高可用的技术主要包括持久化、复制、哨兵和集群,下面分别说明它们的做用,以及解决了什么样的问题。函数
持久化:持久化是最简单的高可用方法(有时甚至不被归为高可用的手段),主要做用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。
复制:复制是高可用Redis的基础,哨兵和集群都是在复制基础上实现高可用的。复制主要实现了数据的多机备份,以及对于读操做的负载均衡和简单的故障恢复。缺陷:故障恢复没法自动化;写操做没法负载均衡;存储能力受到单机的限制。
哨兵:在复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操做没法负载均衡;存储能力受到单机的限制。
集群:经过集群,Redis解决了写操做没法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。
2、Redis 持久化概述日志
持久化的功能:Redis是内存数据库,数据都是存储在内存中,为了不进程退出致使数据的永久丢失,须要按期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复。除此以外,为了进行灾难备份,能够将持久化文件拷贝到一个远程位置。server
Redis持久化分为RDB持久化和AOF持久化:前者将当前数据保存到硬盘,后者则是将每次执行的写命令保存到硬盘(相似于MySQL的binlog);因为AOF持久化的实时性更好,即当进程意外退出时丢失的数据更少,所以AOF是目前主流的持久化方式,不过RDB持久化仍然有其用武之地。进程
下面依次介绍RDB持久化和AOF持久化;因为Redis各个版本之间存在差别,如无特殊说明,以Redis3.0为准。
3、RDB持久化
RDB持久化是将当前进程中的数据生成快照保存到硬盘(所以也称做快照持久化),保存的文件后缀是rdb;当Redis从新启动时,能够读取快照文件恢复数据。
RDB持久化的触发分为手动触发和自动触发两种。
1) 手动触发
save命令和bgsave命令均可以生成RDB文件。
save命令会阻塞Redis服务器进程,直到RDB文件建立完毕为止,在Redis服务器阻塞期间,服务器不能处理任何命令请求。
而bgsave命令会建立一个子进程,由子进程来负责建立RDB文件,父进程(即Redis主进程)则继续处理请求。
此时服务器执行日志以下:
bgsave命令执行过程当中,只有fork子进程时会阻塞服务器,而对于save命令,整个过程都会阻塞服务器,所以save已基本被废弃,线上环境要杜绝save的使用;后文中也将只介绍bgsave命令。此外,在自动触发RDB持久化时,Redis也会选择bgsave而不是save来进行持久化;下面介绍自动触发RDB持久化的条件。
2) 自动触发
save m n
自动触发最多见的状况是在配置文件中经过save m n,指定当m秒内发生n次变化时,会触发bgsave。
例如,查看redis的默认配置文件(Linux下为redis根目录下的redis.conf),能够看到以下配置信息:
其中save 900 1的含义是:当时间到900秒时,若是redis数据发生了至少1次变化,则执行bgsave;save 300 10和save 60 10000同理。当三个save条件知足任意一个时,都会引发bgsave的调用。
save m n的实现原理
Redis的save m n,是经过serverCron函数、dirty计数器、和lastsave时间戳来实现的。
serverCron是Redis服务器的周期性操做函数,默认每隔100ms执行一次;该函数对服务器的状态进行维护,其中一项工做就是检查 save m n 配置的条件是否知足,若是知足就执行bgsave。
dirty计数器是Redis服务器维持的一个状态,记录了上一次执行bgsave/save命令后,服务器状态进行了多少次修改(包括增删改);而当save/bgsave执行完成后,会将dirty从新置为0。
例如,若是Redis执行了set mykey helloworld,则dirty值会+1;若是执行了sadd myset v1 v2 v3,则dirty值会+3;注意dirty记录的是服务器进行了多少次修改,而不是客户端执行了多少修改数据的命令。
lastsave时间戳也是Redis服务器维持的一个状态,记录的是上一次成功执行save/bgsave的时间。
save m n的原理以下:每隔100ms,执行serverCron函数;在serverCron函数中,遍历save m n配置的保存条件,只要有一个条件知足,就进行bgsave。对于每个save m n条件,只有下面两条同时知足时才算知足:
(1)当前时间-lastsave > m
(2)dirty >= n