zoukankan      html  css  js  c++  java
  • Redis 复制原理及分析

    1.测试                                                                

     见master-slave测试帖

    2 原理

    第一次、Slave向Master同步的实现是:

            Slave向Master发出同步请求(发送sync命令),Master先dump出rdb文件,然后将rdb文件全量传输给slave,然后Master把缓存的写命令转发给Slave,初次同步完成。
    第二次、以及以后的同步实现是:
            Master将变量的快照直接实时依次发送给各个Slave。
            但不管什么原因导致Slave和Master断开重连都会重复以上两个步骤的过程。
            Redis的主从复制是建立在内存快照的持久化基础上的,只要有Slave就一定会有内存快照发生。      

    )

    但是,我们可以很明显的看到,RDB有他的不足,就是一旦Redis出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到 Redis停机这段时间的数据全部丢掉了。在某些业务下,这是可以忍受的,我们也推荐这些业务使用RDB的方式进行持久化,因为开启RDB的代价并不高。 但是对于另外一些对数据安全性要求极高的应用,无法容忍数据丢失的应用,RDB就无能为力了,所以Redis引入了另一个重要的持久化机制:AOF日志,稍后分析。

     

    3. Rdb快照原理

     Redis支持将当前数据的快照存成一个数据文件的持久化机制,即RDB快照。这种方法是非常好理解的,但是一个持续写入的数据库如何生成快照呢?

     Redis借助了fork命令的copy on write机制(私有内存非共享内存)。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。

           我们可以通过Redis的save指令来配置RDB快照生成的时机,比如你可以配置当10分钟以内有100次写入就生成快照,也可以配置当1小时内有 1000次写入就生成快照,也可以多个规则一起实施。这些规则的定义就在Redis的配置文件中,你也可以通过Redis的CONFIG SET命令在Redis运行时设置规则,不需要重启Redis。

            在redis中配置:

            1、save  900 1              #当900秒内有一条Keys数据被改变时,生成RDB;
            2、save 300  10            #当300秒内有10条Keys数据被改变时,生成RDB;
            3、save 60    10000     #当60秒内有10000条Keys数据被改变时,生成RDB;

    ################################ SNAPSHOTTING  #################################
    #
    # Save the DB on disk:
    #
    #   save <seconds> <changes>
    #
    #   Will save the DB if both the given number of seconds and the given
    #   number of write operations against the DB occurred.
    #
    #   In the example below the behaviour will be to save:
    #   after 900 sec (15 min) if at least 1 key changed
    #   after 300 sec (5 min) if at least 10 keys changed
    #   after 60 sec if at least 10000 keys changed
    #
    #   Note: you can disable saving at all commenting all the "save" lines.
    
    save 900 1
    save 300 10
    save 60 10000

    4. Redis的AOF日志

         AOF日志的全称是append only file,从名字上我们就能看出来,它是一个追加写入的日志文件。与一般数据库的binlog不同的是,AOF文件是可识别的纯文本,它的内容就是一个个 的Redis标准命令。当然,并不是发送到Redis的所有命令都要记录到AOF日志里面,只有那些会导致数据发生修改的命令才会追加到AOF文件。

    那么每一条修改数据的命令都生成一条日志,那么AOF文件是不是会很大?
            答案是肯定的,AOF文件会越来越大,所以Redis又提供了一个功能,叫做AOF rewrite(使用Redis提供了bgrewriteaof命令就可以)。其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像一份老文件那样,可能记录了对同一个值的多次操作。其生成过程和RDB类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件(这个过程和RDB类似,但是是将数据拆分成一条一条写命令的形式的)。在写入新文件的过程中,所有的写操作日志还是会写到原来老的 AOF文件中,同时还会记录在内存缓冲区中。当重完操作完成后,会将所有缓冲区中的日志一次性写入到临时文件中。然后调用原子性的rename命令用新的 AOF文件取代老的AOF文件。(这样的操作,老的AOF可以恢复内存,如果产生新的AOF,老的就不存在了,可用新的AOF文件恢复内存,这样同时解决了AOF不断增长的问题。)AOF是一个写文件操作,其目的是将操作日志写到磁盘上,所以它也同样会遇到我们上面说的写操作的5个流程。

    那么写AOF的操作安全性又有多高呢?

    实际上这是可以设置的,在Redis中对AOF调用write(2)写入后,何时再调用fsync将其写到磁盘上,通过appendfsync选项来控制,下面 appendfsync的三个设置项,安全强度逐渐变强。

    1)appendfsync no
            当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。

    2)appendfsync everysec
            当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多 长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。

            结论就是,在绝大多数情况下,Redis会每隔一秒进行一 次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。

    3)appendfsync always
            置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,
    所以其性能也会受到影响。

    Redis数据恢复:
    RDB的启动时间会更短,原因有两个:
    一、RDB文件中每一条数据只有一条记录,不会像AOF日志那样可能有一条数据的多次操作记录。所以每条数据只需要写一次就行了。
    二、RDB文件的存储格式和Redis数据在内存中的编码格式是一致的,不需要再进行数据编码工作,所以在CPU消耗上要远小于AOF日志的加载。

    5. Redis的Rdb文件

    在slave server执行sync命令,请求同步,如下返回rdb文件,为二进制文件,

    redis 127.0.0.1:6380> sync
    "REDIS0002xfex00
    anumbersx0fx0fx00x00x00
    x00x00x00x01x00x00xc0
    x03x00xffx00x03oldxc0x01x00keywatchxc0x03x00x04namex05kerryx00x0
    3aaaxc0ox02alettersx02x01cx01b	x04car1x19x02x04namex05x00AUDIOx05p
    ricex03x0030wxff	x04car2x19x02x04namex05x00AUDIOx05pricex03x0020wx
    ff	x04car3x19x02x04namex05x00buickx05pricex03x0010wxffx00x03keyx03
    aaax00x03numxc0x04x00x02a1xc0x01x00x02a2xc0x02x00x06keynewxc0x04
    x00x02a3xc0x03x02letters2x03x01cx01dx01ex00acompanyx03alux00x0co
    ldvalue=GETx03oldxff"
    redis 127.0.0.1:6380>

    具体文件为redis目录下,如下所示:

    6. Redis的AOF文件

    默认关闭,打开AOF设置,如下

    ############################## APPEND ONLY MODE ###############################
    
    # By default Redis asynchronously dumps the dataset on disk. If you can live
    # with the idea that the latest records will be lost if something like a crash
    # happens this is the preferred way to run Redis. If instead you care a lot
    # about your data and don't want to that a single record can get lost you should
    # enable the append only mode: when this mode is enabled Redis will append
    # every write operation received in the file appendonly.aof. This file will
    # be read on startup in order to rebuild the full dataset in memory.
    #
    # Note that you can have both the async dumps and the append only file if you
    # like (you have to comment the "save" statements above to disable the dumps).
    # Still if append only mode is enabled Redis will load the data from the
    # log file at startup ignoring the dump.rdb file.
    #
    # IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append
    # log file in background when it gets too big.
    
    appendonly yes

    windwos下无法生成,可能兼容性有问题。生成的aof文件与rdb文件在同目录下。

  • 相关阅读:
    安装jdk
    chrome
    Jenkins启动
    Red Hat Linux分辨率调整
    Jemeter第一个实例
    grep与正则表达式
    使用ngx_lua构建高并发应用
    UML建模之时序图(Sequence Diagram)
    secureCRT mac 下破解
    跨域通信的解决方案JSONP
  • 原文地址:https://www.cnblogs.com/jking10/p/6054696.html
Copyright © 2011-2022 走看看