redis的过期策略

  最近把内存淘汰策略和过期策略搞混了。。。。

  Redis的过期策略就是指当Redis中缓存的key过期了,Redis是怎么处理的

  Redis的过期策略有三种:

    • 定时删除

      在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作,并释放过期键占用的内存。

      优点:对内存友好

      缺点:对CPU时间非常不友好

    • 惰性删除

      只有当访问到一个key时,才会检查key有没有过期,过期则删除,返回-1;没有过期则返回该键。

      优点:对CPU时间非常友好

      缺点:对内存非常不友好(存在键过期,但是一致没有访问到,则会一直存在内存中)

    • 定期删除

      每隔一段时间,程序对数据库进行一次检查,删除里面的过期key,至于要删除那些数据库的过期key,则由算法决定。

      定期删除策略每隔一段时间执行一次删除过期键的操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响,同时通过定期删除过期键,也有有效的减少了因为过期键带来的内存浪费。

  Redis使用的是惰性删除和定期删除。

  • 惰性删除的实现

    Redis对所有读写数据库的命令在执行前,都会调用expiredIfNeeded对键进行检查。如果输入的键已经过期,那么将输入键从数据库中删除;否则不做任何处理。

  • 定时删除

    过期键的定时删除是由activeExpireCycle函数实现的,每当Redis服务器的周期性操作serverCron函数执行时,activeExpiredCycle函数就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的expires字典中随机检查一部分键的过期时间,并删除其中的过期键。

    在csdn上面找了一段activeExpireCycle的伪代码

#默认每次检查的数据库数量
DEFAULT_DB_NUMBERS = 16
#默认每个数据库检查的键数量
DEFAULT_KEY_NUMBERS = 20
#全局变量,记录检查进度
current_db = 0
def activeExpireCycle():
    # 初始化要检查的数据库数量
    # 如果服务器的数据库数量比 DEFAULT_DB_NUMBERS 要小
    # 那么以服务器的数据库数量为准
    if server.dbnum < DEFAULT_DB_NUMBERS:
        db_numbers = server.dbnum
    else:
        db_numbers = DEFAULT_DB_NUMBERS
    # 遍历各个数据库
    for i in range(db_numbers):
        # 如果current_db 的值等于服务器的数据库数量
        # 这表示检查程序已经遍历了服务器的所有数据库一次
        # 将current_db 重置为0 ,开始新的一轮遍历
        if current_db == server.dbnum:
            current_db = 0       
        # 获取当前要处理的数据库
        redisDb = server.db[current_db] 
        # 将数据库索引增1 ,指向下一个要处理的数据库
        current_db += 1 
        # 检查数据库键
        for j in range(DEFAULT_KEY_NUMBERS):
            # 如果数据库中没有一个键带有过期时间,那么跳过这个数据库
            if redisDb.expires.size() == 0: break
            #随机获取一个带有过期时间的键
            key_with_ttl = redisDb.expires.get_random_key()
            # 检查键是否过期,如果过期就删除它
            if is_expired(key_with_ttl):
                delete_key(key_with_ttl)
            # 已达到时间上限,停止处理
            if reach_time_limit(): return

     activeExpireCycle的处理过程是,每次遍历指定的db数,和每次查询的key的数,如果当前Redis的db_num数量大于默认的db数,则指定的db数为redis的db_num,并且遍历某个db时,会判断当前db有没有键设置过期时间,如果没有一个键设置了过期时间,那么跳过当前数据库;如果当前数据库中的过期key占key的填充率不足1%,则也跳过该数据库;如果当前数据库设置过期时间的key数小于默认的需要查询的key数,则设置当前数据库需要查询的key的数目为当前数据库的过期key的数目,否则随机获取一个带有过期键的key,判断key是否过期,过期则删除,并且进行广播,告诉从库删除,并将del操作写如果aof。    

      

posted on 2020-08-23 22:50  `Elaine  阅读(224)  评论(0编辑  收藏  举报

导航