redis持久化机制与过期策略

RDB的持久化策略

(快照方式,默认持久化方式): 按照规则定时将内存中的数据同步到磁盘,它有以下4个触发场景。

  1. 自己配置的快照规则  vim /redis/bin/ redis.conf;按照save <seconds> <changes>这个规则自己添加或修改规则。

    

  2. save或者bgsave命令

    save:将内存的数据同步到磁盘中,这个操作会阻塞客户端的请求(不建议用,太耗时了)。

      bgsave:在后台异步执行快照操作,这个操作不会阻塞客户端的请求。

  3. 执行flushall清除内存的所有数据时,只要save <seconds> <changes>规则不为空,就会执行快照。

  4. 执行复制的时候(集群中 )

  快照的实现原理与优缺点:

    redis使用fork函数复制出一份当前进程的副本(子进程);父进程继续处理客户端指令,子进程开始将内存的数据写入硬盘中的临时文件,写入完成后就会替换之前的旧文件。优点:1. 多进程处理,性能最快。缺点:1. 若子进程数据未写完而redis异常退出,就会丢失最后一次快照以后更改的所有数据; 2. 如果数据集比较大的时候,fork可以能比较耗时,造成服务器在一段时间内停止处理客户端的请求。

AOF的持久化策略

  开启AOF持久化vim /redis/bin/ redis.conf  将appendonly默认值no改为yes; 重启后执行对数据的变更命令, 会在bin目录下生成对应的.aof文件, aof文件中会记录所有的操作命令!

    

  AOF优化:

     auto-aof-rewrite-percentage 100  表示当前aof文件大小超过上一次aof文件大小的百分之多少的时候会进行重写。如果之前没有重写过,以启动时aof文件大小为准

     auto-aof-rewrite-min-size 64mb   限制允许重写最小aof文件大小,也就是文件大小小于64mb的时候,不需要进行重写。

    

   aof重写原理:

    执行redis命令的时候,会把命令写入到.aof文件中,.aof文件变得过大时后台会对它进行重写。在将命令写入到.aof时,即使重写过程发生了停机,现有的.aof文件也不会丢失,所以它是绝对安全的。

   同步磁盘数据:

    redis在变更数据时,命令会实时记录到.aof文件。但是由于操作系统的缓存机制,数据不是直接写入到硬盘,而是写入硬盘缓存,再通过硬盘缓存机制刷新保存到文件。

      appendfsync always  每次执行写入都会进行同步  , 这个是最安全但是是效率比较低的方式

      appendfsync everysec   每一秒执行

      appendfsync no  不主动进行同步操作,由操作系统去执行,这个是最快但是最不安全的方式

      

  2.4 aof文件损坏以后如何修复:

    例如在执行set name wulei时候,文件只记录了set name  ,这种不完整的命令是无法被写入磁盘的。我们可以先将.aof文件备份,然后通过redis-check-aof --fix命令修复,它会将一些不合法的命令清理掉,这样就能被持久化了。

  如果要保证数据绝对安全: 可以使用  RDB+AOF 方式来持久化。如果同时使用的话, 那么Redis重启时,会优先使用AOF文件来还原数据。

  如果可以接受几分钟的数据丢失:可以使用RDB方式,因为AOF速度没有RDB快。

============================  手动分割线  ==============================

Redis的过期策略

  redis过期是(定期删除+惰性删除+内存淘汰机制)来实现的。reids是用内存来缓存的,内存资源很宝贵。所以我们 set key value 的时候一般都会给它设置过期时间。假设redis里放了10万个数据,redis默认会每隔100ms随机抽取设置了过期时间的key来删除(如果一次性检查所有数据,cpu负载过高redis早就死了),这种方式就叫定期删除。这种策略就会导致很多过期的key并没有被删除,所以还有惰性删除, 也就是在你获取某个key的时候,redis会检查一下,这个key是否过期了,如果是就直接删除不返回任何东西!

  但是这种方式还是有问题的,比如10万条全过期了,而redis只定期删除了部分,而客户端有没有对剩下的key操作,key就不会被删除,还是会造成内存的积压。这时候就会走内存淘汰机制,例如:

    allkeys-lru:当内存不足以容纳新写入数据时,移除最近最少使用的key。(最常用)

    volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键中,将更早过期时间的key优先移除。(还凑合吧)

    noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。(脑残的策略,没人用)

    allkeys-random:当内存不足以容纳新写入数据时,随机移除某个key。(脑残的策略,没人用)

    volatile-lru:当内存不足以容纳新写入数据时,在设了过期时间的键中,移除最近最少使用的key。(脑残的策略,没人用)

    volatile-random:当内存不足以容纳新写入数据时,在设了过期时间的键中,随机移除某个key。(脑残的策略,没人用)

缓存淘汰算法LFU算法

  lfu算法是根据数据的历史访问频率来淘汰数据的,其核心思想是"如果数据过去被访问多次,那么将来被访问的频率也更高".
  缺点:
  1. 有存储成本,需要维护队列的引用计数,2.最后添加的数据容易被移除
LFU算法原理剖析
  1. 新加入的数据插入到队列尾部(因为引用计数为1)
  2. 队列中的数据被访问后,其引用计数增加,队列重新排序
  3. 当需要淘汰数据时,将已经排序的列表最后的数据块删除

  

缓存淘汰算法LRU算法

  根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”
LRU算法原理剖析
  1. lru按照一定顺序维护着队列
  2. 队列中的数据被访问后,数据会被排列到最前面
  3. 当需要淘汰数据时,将已经排序的列表最后的数据块删除
  

手写LRU算法

import java.util.LinkedHashMap;
import java.util.Map;

// lru是有序的,所以这里继承 LinkedHashMap
public class LRUCache<K,V> extends LinkedHashMap<K,V> {

    private final int CACHE_SIZE;
    /**
     * 传递进来最多能缓存多少数据
     *
     * @param cacheSize 缓存大小
     */
    public LRUCache(int cacheSize) {
        /*
            cacheSize是map的初始大小
            0.75f是加载因子,容量使用率达到0.75就会扩容一倍
            true 表示让 linkedHashMap 按照访问顺序来进行排序,最近访问的放在头部,最老访问的放在尾部。
         */
        super(cacheSize, 0.75f, true);
        CACHE_SIZE = cacheSize;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        // 当前map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据。
        boolean b = size() > CACHE_SIZE;
        if(b){
            System.out.println("清除缓存key:"+eldest.getKey());
        }
        return b;
    }
    public static void main(String args[]){
        LRUCache<String, String> lruCache = new LRUCache<String, String>(3);
        lruCache.put("1", "1");
        lruCache.put("2", "2");
        lruCache.put("3", "3");
        lruCache.put("4", "4");
        System.out.println("初始化完成:"+lruCache.keySet());
        System.out.println(lruCache.get("3"));
        System.out.println("访问3之后:"+lruCache.keySet());
        System.out.println(lruCache.get("2"));
        System.out.println("访问2之后:"+lruCache.keySet());
    }
}

 

posted @ 2018-10-24 11:45  吴磊的  阅读(1155)  评论(0编辑  收藏  举报
//生成目录索引列表