总结与归纳Redis持久化、可靠性等

该文章是将近期学习Redis的基础知识进行总结和归纳,纯手打。
大篇幅、纯文字。
慎看

Redis是一个单线程的内存数据库,在主线程中处理命令操作,但是其余的一些操作,比如:rdb快照、AOF日志重写等,都需要主线程fock一个子进程出来处理,所以实际上,Redis不完全就是单线程。

由于Redis是将数据保存到内存上的,所以它的速度是非常快的,但是也容易数据丢失,所以Redis大多数是用来做缓存数据库。

那么如何来保证Redis的数据的可靠性?
这使用了AOF日志以及RDB快照,来保证数据少丢失。
也使用了主从库、哨兵、哨兵集群,来保证链接断开后的处理。

AOF日志是一个写后日志,就是命令执行成功后,将命令写入到AOF日志中。
由于是在写后操作日志,所以不会影响到其他的命令的操作。
但是AOF是一个Append Only File 只能写入的文件,那只要一直有命令操作传输到Redis,那么AOF日志就会不断的变大, 那相应的操作AOF的速度就会降低,同时就会影响到Redis客户端与应用程序响应的速度。

这时就会使用AOF日志重写,日志重写是在子进程中操作,所有不会阻塞主线程,但是子进程是通过主线程fock出来的,这个fock的过程还是会阻塞主线程,这个阻塞的时间取决于主线程中数据结构(包含内存页表)的大小,越大,阻塞时间越长。若是使用了系统中的内存大页机制(Huge Page),那么就会是阻塞的概率大大增加,所以Redis系统,需要取消内存大页机制。

AOF日志重写,是将当前数据库的最新数据,生成一行命令。比如在旧AOF日志中,有使用PUSH POP RPOP LPUSH操作同一个key,那么在新的AOF中,只有一条命令 PUSH key field,这样就节省了3条命令的内存。

AOF是一直需要将命令保存,并将AOF日志存到磁盘中,时间长了会有很大开销,速度也会变慢。同时若要恢复数据的话, 就需要把日志里的命令全部都执行一遍,那恢复数据的速度就会非常慢。

那么有什么速度会很快的?
RDB内存快照就相当于拍照片,我们是拍人、拍风景,而内存快照,是“拍”数据
,把某个时刻T0的数据拍下来,生成RDB文件,存放到缓存中,由于RDB文件保存的是数据,那么只需要让内存读取到RDB就能快速恢复数据了。

生成RDB的过程也是在子进程中处理,所以不会阻塞主线程。在生成RDB的时候,正常我们是不允许再改动数据的,但是不能进行写入操作,显然也是不可能的,这时就运用到了“写时复制”,操作的key存在的话,就会将要操作的key数据块复制出来变成一个数据副本,然后RDB读取副本,将副本数据重新写入到缓存中。

生成RDB的时间点要如何设计?如果时间间隔太短的话,就会使主线程频繁的fock子进程,会造成主线程拥塞, 同时也可能会造成第一次的快照还没有结束,第二次快照就开始了,会造成恶性循环。若时间间隔太长的话,Redis系统可能在这区间宕机了,那么在这段区间的数据就会丢失。

Redis就很人性化的提供了RDB与AOF日志混合使用的方法,也就是RDB时间可以设置的长一点,在生成RDB后的T0到T1这区间就会使用AOF日志,在T1时刻到来的时候,就会将AOF日志清空。

由于AOF日志只记录了T0-T1时刻的命令,那就不需要执行全局的命令来恢复数据,那么恢复数据的速度就不会很慢。
这方案,就能同时体验AOF日志只记录命令的便利以及RDB恢复数据的快速。

以上只是保证了数据不丢失的情况,但是有可能会再执行AOF日志或者RDB的时候宕机了,数据始终会有丢失。

那么就又提出了三个方案:主从复制、哨兵、哨兵集群

主从复制有一个从库链接到主库,主库响应后,传输RDB文件到从库,从库将自身的数据都清空后执行RDB文件,这就实现了主从复制。

主从库之间怎么进行连接 、数据传输的呢?
分为三个步骤:
步骤1:从库与主库进行连接(replicaof命令)然后向主库发送psync runid offset(runid是主库id,由于是第一次连接还不知道,所以会是"?";offset是偏移量,第一次连接,偏移量为-1),然后主库会发送FULLRESYNC runid offset命令,通知从库将进行第一个全量同步,并将runid和偏移量发送到从库中,从库将主库信息进行保存。

步骤2:主库生成RDB文件(fock子进程会造成主线程阻塞),将RDB文件传输到从库中(会占用主库的带宽),从库接收到RDB后,将数据清空,然后再执行RDB文件(防止数据错误)。

步骤3:传输RDB文件过程中,又有数据进入主库,会进入到主库的replication_buffer中,等RDB文件传输结束后,再将replication_buffer的数据再传输到从库。

此时若主从链接断掉了,从库重新连接主库后,会进行上面的操作,在此进行全量同步,这数据量会持续增大,这就会有很大的开销,显然这是不能接受的。

还好Redis2.8之后,主从链接断开重连后,会进行增量复制,这就大大减少了开销。那么我们来看看是怎样进行增量复制的。

若主从断开后,新数据会进入replication_buffer再进到repl_backlog_buffer(扇形缓冲区),最开始的时候,该主库的偏移量(master_repl_buffer)与从库的偏移量(slave_repl_buffer)在该缓冲区的起始位置是一样的, 主库写入后,偏移量会慢慢增大, 同时从库读取后偏移量也会慢慢增大,这两个偏移量正常情况下是一致的。

但是因为是扇形缓冲区,就要注意,若主从链接迟迟没有连接上的话,主库在repl_backlog_buffer的偏移量会一直增加,但是从库的偏移量始终都没有追上主库的偏移量,这时,反而主库的偏移量追上了从库的偏移量,就会导致有些数据从库还没来得及复制,就被主库新的数据给覆盖了。

这时就可以设置扇形缓冲区repl_backlog_size的大小,正常来说要配置得偏大一点,防止上述情况发生。

若从库有多个的时候,就会有多个从库向主库发送请求,主库响应后会fock多个子进程出来生成rdb文件,并传输rdb文件,这些都会使主库的压力过大,要怎么给主库分担压力呢?

这就需要使用到**“主-从-从”**模式,主从从模式就是父亲管哥哥,哥哥去管弟弟,若弟弟多了,也可以让弟弟去管弟弟。
例如:实例1为主库,实例2和实例3为从库,那么若实例2和3都从主库复制数据的话,就可能会造成主库的压力过大,这时候就可以将实例2划为实例3的主库,实例1将数据发送到实例2后,实例3与实例2连接,实例2就会将数据发送到实例3中。这就会降低实例1的压力。

使用一下命令使从库与主库连接,redis5.0之前使用的是slaveof

redis[0] -> replicaof ip 6379

这时我们来想一下,若主库宕机了,怎么办?

主库宕机了就需要在从库中选择一个来当主库,这个过程就是通过“哨兵”机制完成的,“哨兵”其实是运行在特定条件下的redis实例,通过“哨兵”来对主库进行监听、换主、通知的过程。若有哨兵断掉了,还有其他哨兵的存在的话,也不会影响主从库的切换,但是这就需要配置哨兵集群。每个哨兵在连接redis客户端的时候通过PUB\SUB(发布\订阅)机制,将自身的ip与端口发布到指定的频道中,然后其他哨兵就会订阅该频道,获取到其他哨兵的ip、端口,进行网络连接,这样,哨兵集群就形成了。

那么监听、换主、通知的过程是什么呢?
顾名思义,监听就是监听主从库的状态、换主就是换新主库、通知就是通知其他哨兵以及Redis客户端新主库的信息。
详细来说一下:
1.监听、每个哨兵会通过PING命令与主库进行交互,若主库在规定时间内没有响应的话,就标记为主观下线,但这只是各个哨兵的主观意见,若就以“主观下线”来更换主库的话,就可能会有误操作,实际上主库并没有下线,但是还切换主库,就会造成不必要的开销。这就需要每个哨兵与其他哨兵进行“沟通”,收集到其他哨兵对主库的意见后,归纳判断“主观下线”的哨兵有多少个,若有N/2+1个哨兵判断为“主观下线”,那么就将主库标记为**“客观下线”**,这时就可以基本判定主库下线了,接线来就到了换主的过程。

2.换主、在“监听”的过程,给主库判定为“客观下线”的哨兵,可以说“我想当Leader!”,有其他的哨兵进行投票,每个哨兵都只能投一张票(YES OR NO),若有N/2+1张赞成票,那该哨兵就成为“Leader哨兵”,将进行换主的任务。换主过程,有三步筛选:第一步、筛选掉掉线的从库。第二步、从当前从库中,筛选掉网络不稳定的从库。第三步、首先判断从库的优先级(可以通过配置slave_priority),若不匹配,再判断从库与旧主库间的数据是否接近(计算master_repl_offset【主库偏移量】与slave_repl_offset【从库偏移量】的差距),若差距小就使用该从库,若没有匹配的从库,则进行最后的判断,查找RUNID最小的从库,使用该从库当主库。

到这,换主的过程就结束了。换完主之后,就需要通知给其他哨兵和从库以及Redis客户端新主库的信息啦!

3.通知、首先Leader哨兵将新主库的信息PUB发布到指定的频道中,其他哨兵SUB订阅该频道获取新主库信息。然后Leader哨兵使用INFO命令与Redis客户端沟通,取得从库的信息,然后将新主库信息发送到从库并执行replicaof命令,进行数据传输。最后因为哨兵时特定条件允许下的redis实例,所以每个哨兵都有自己个PUB\SUB机制,Redis客户端通过订阅哨兵的订阅\发布机制中,特定的频道,就能获取到新主库的信息,与新主库进行连接,将接下来的命令都传输到新主库中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值