• Redis学习笔记(四):过期策略、持久化、事件


     图片来自《Redis设计与实现》
     
    Redis数据库
        redis.server中redisServer.dbnum用于初始化生成多少个数据库,默认16个,Select命令选择数据库
        redis.client中redis.db指针指向当前正在使用的数据库
     
    一、过期策略
        设置过期时间命令expire如  expire <key> <ttl>
     
        redisDb主要由dict和expires两个字典组成:
                dict 为键空间字典,存放该数据库中所有的键对象;expires参数称为过期字典,存放每个键对应的过期时间
                expires的键是一个指针,指向键空间中的某个键对象;值是long long类型的整数,存放过期时间(毫秒UNIX时间戳(chuo))
     
        两步判断键是否过期
                (1)检查给定键是否存在于过期字典;存在,则获得对应的时间戳
                (2)获取当前UNIX时间戳,两者进行比较,即可知道是否过期
     
        三个过期键删除策略:
                1.定时删除:使用定时器(基于时间事件,无序链表,复杂度O(N),无法高效处理大量时间事件),定时检查键是否过期,对内存友好的策略
                2.惰性删除:使用键时才去检查该键是否过期,对CPU友好的策略
                3.定期删除:折中的策略,随机检查一部分键的过期时间并删除其中过期的键,难点是确定删除执行的时长和频率
        Redis中采用 惰性删除 和 定期删除 配合使用
     
        由于两种过期键删除策略仍然可能会导致大量过期键堆积在内存,为此,Redis引入的内存淘汰机制(淘汰策略共6种。最重要的是 allkeys-lru)
     
        过期键对RDB、AOF持久化以及复制的影响
                RDB:RDB持久化时,会检查键是否过期;RDB载入时,主服务器会检查键是否过期,从服务器忽略,等待主服务器同步时处理
                AOF:AOF文件写入时忽略,直到过期键被删除,才向AOF文件追加一条删除过期键的命令 
                           AOF文件重写时,会检查键是否过期
                复制:主服务器每删除一个过期键,则显示地向所有从服务器发送一个DEL命令,通知从服务器删除过期键
                    (这个其实就是主从复制的同步流程?)
               
    二、持久化
        Redis的持久化分为两种:RDB持久化 和 AOF持久化
     
        RDB持久化:
             一个经过压缩的二进制文件;以键值对形式存储数据库信息,不同的键值对使用不同的方式保存
     
            两个命令的区别:SAVE,BGSAVE
                save:阻塞式RDB持久化。服务器线程执行RDB持久化操作,期间不能处理任何命令请求
                bgsave:非阻塞式RDB持久化。会创建一个子进程用于执行RDB持久化操作,服务器线程仍然能处理命令请求
     
            RDB文件载入
                无命令,服务器启动时自动执行;若服务器开启了AOF持久化功能, 会优先使用AOF文件来还原数据库状态
     
            RDB自动间隔性保存
                可配置服务器save选项,每隔一段时间自动执行一次bgsave命令
                
                默认满足三个条件之一,则自动执行一次bgsave命令。条件存储在 saveparams 参数中
                除saveparams数组外,还存储 dirty计数器  lastsave属性;dirty用于计算累积操作次数,lastsave用于和当前时间戳比较,计算经过的时间
                三个条件:900 1;300 10;60 10000
     
                Redis的周期性操作函数 serverCron 默认每间隔100ms执行一次,用于对正运行的服务器维护,其中就包括检查参数条件是否满足
     
        AOF持久化:
            通过保存Redis命令来保存数据库信息
            以Redis命令请求协议格式保存,Append Only File
     
            三步实现AOF持久化:
                (1)命令追加:每执行一个命令,就将命令追加到aof_buf缓冲区(常量值大小64)末尾
                (2)命令写入:服务器每次结束一个事件循环前,都会调用flushAppendOnlyFile函数,考虑是否将缓冲区数据写入AOF文件
                (3)命令同步:与flushAppendOnlyFile函数的 appendfsync 参数决定
                                always:缓冲区写入并同步到AOF文件
                                everysec:每秒同步一次
                                no:只写入,由操作系统决定同步
     
            AOF的载入还原:
                (1)创建一个不带网络连接的伪客户端(用于执行AOF文件中的Redis命令,因为命令只能在客户端中执行)
                (2)从AOF文件中分析并读取出一条命令
                (3)伪客户端执行命令
                (4)循环执行2,3;直到AOF文件中的命令执行完毕
     
            AOF的文件重写:   bgrewriteaof
                为什么需要:为了解决随时间和操作的增长,AOF文件的膨胀问题,处理AOF文件中命令冗余
                实现理念:不是读取原有AOF文件内容,而是直接读取当前数据库状态,然后用一条(或多条,尽量少的)命令去记录键值对
                实现过程:
                        1.创建一个子进程后台执行重写 --- 避免使用锁的情况下,保证数据安全;且不阻塞服务器进程
                        2.使用了AOF重写缓冲区,服务器每执行一个命令,都将命令同时追加到AOF缓冲区和AOF重写缓冲区
                        3.重写工作完成后,子进程返回一个信号,父进程调用信号处理函数
                            (1)将AOF重写缓冲区的内容写入新AOF文件中,使新AOF文件与数据库状态一致
                            (2)对新AOF文件改名,原子性地覆盖现有AOF文件,完成新旧AOF文件交替
                            注意:调用信号处理函数阶段,服务器进程阻塞。(重写过程中就这一处阻塞
     
        RDB与AOF两种持久化方式的比较
        (1)RDB文件小,恢复快;但是无法保存最近一次快照后的数据,即会丢失这部分数据
        (2)AOF文件可读性高,数据不易丢失;但是文件体积大,恢复时间长
        Redis 4.0 开始支持 RDB 和 AOF 的混合持久化
     
       
    三、事件
             Redis 服务器是一个事件驱动程序
            单线程运行,I/O多路复用来监听多个套接字;有两种事件(文件事件和时间事件)
     
            文件事件:对套接字进行操作的抽象;有可读事件、可写事件;文件事件拥有基于Reactor模式的文件事件处理器。           
      文件事件处理器: 套接字 + I/O多路复用程序 + 文件事件分派器 + 事件处理器
      常见事件处理器:连接应答处理器,命令请求处理器,命令回复处理器。(依次为连接、接收命令、处理命令回复)

      时间事件:给定的时间点执行类操作的抽象;有定时事件、周期性事件

      时间事件实现: Redis 将所有时间事件都放在一个无序链表(不按when属性大小排序)中,通过遍历整个链表查找出已到达的时间事件,并调用相应的事件处理器。

      时间事件:三个参数(id,when,timeProc);典型事件:serverCron

     
            事件调度与执行
    def aeProcessEvents():
    # 获取到达时间离当前时间最接近的时间事件
    time_event = aeSearchNearestTimer()
    # 计算最接近的时间事件距离到达还有多少毫秒
    remaind_ms = time_event.when - unix_ts_now()
    # 如果事件已到达,那么 remaind_ms 的值可能为负数,将它设为 0
    if remaind_ms < 0:
    remaind_ms = 0
    # 根据 remaind_ms 的值,创建 timeval
    timeval = create_timeval_with_ms(remaind_ms)
    # 阻塞并等待文件事件产生,最大阻塞时间由传入的 timeval 决定
    aeApiPoll(timeval)
    # 处理所有已产生的文件事件
    procesFileEvents()
    # 处理所有已到达的时间事件
    processTimeEvents()
     
  • 相关阅读:
    【接口平台】上报接口处理时间
    【性能测试】吞吐量上不去的问题
    vue层级选择器多选
    打家劫舍 II
    打家劫舍
    房屋染色 II
    距离顺序排列矩阵单元格
    根据身高重建队列
    将 x 减到 0 的最小操作数
    确定两个字符串是否接近
  • 原文地址:https://www.cnblogs.com/xiang9286/p/11056654.html
Copyright © 2020-2023  润新知