zoukankan      html  css  js  c++  java
  • 【Redis】Redis的过期策略

    redis过期策略

    在使用redis做缓存的时候,我们常常会设置过期时间。那么redis是如何清理这些过期的数据呢?

    答案是: 定期删除 + 惰性删除

    • 定期删除: redis每100ms就会随机抽查删除过期的数据。但是这种方法有时候会留下大量过期但没有被抽查到的过期数据,白白浪费内存。
    • 惰性删除: 惰性删除此时就派上用场了,当用户获取数据时,redis会先检查该数据有没有过期,如果过期就删除。

    听上去定期删除+惰性删除好像很完美的样子,but过期的数据用户又没有及时访问,那么内存中还是会存在大量的过期数据。此时应该采用redis内存淘汰机制。

    redis内存淘汰机制

    • noeviction:内存不足以写入新数据的时候会直接报错。
    • allKeys-lru:内存不足以写入新数据时候,移除最近最少使用的key。
    • allKeys-random: 内存不足以写入新数据时,随机移除key。
    • volatile-lru: 内存不足以写入新数据时,在设置了过期时间的key当中移除最近最少使用的key。
    • volatile-random: 内存不足以写入新数据时,在设置了过期时间的key中,随即移除key。
    • volatile-ttl: 内存不足以写入新数据时,在设置了过期时间的key当中移除最先过期的key。

    上面六种你可以这么记:

    • 不移除直接报错: noeviction。
    • 在所有key中移除: 1.allKeys-lru 2. allKeys-random
    • 在设置了过期时间的key中移除: 1. volatile-lru 2. volatile-random 3.volatile-ttl

    一般常用allKeys-lru

    实现一个简单的lru(最近最少使用算法)

    package com.amber;
    
    import java.util.Iterator;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
        //最大容量
        private final int maxCapacity ;
        // 默认增长因子
        private static final float DEFAULT_LOAD_FACTOR = 0.75f;
    
        public LRULinkedHashMap(int maxCapacity) {
            super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
            this.maxCapacity = maxCapacity;
        }
        
        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> entry) {
            if(size()>maxCapacity)
                return true;
            else
                return false;
        }
    
        public static void main(String[] args) {
            LRULinkedHashMap<String, String> lruLinkedHashMap = new LRULinkedHashMap(5);
            lruLinkedHashMap.put("1", "1");
            lruLinkedHashMap.put("2", "2");
            lruLinkedHashMap.put("3", "3");
            lruLinkedHashMap.put("4", "4");
            lruLinkedHashMap.put("5", "5");
            Iterator<Map.Entry<String, String>> iterator = lruLinkedHashMap.entrySet().iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }
            lruLinkedHashMap.get("1");
            System.out.println("超出最大容量");
            lruLinkedHashMap.put("6", "6");
            iterator = lruLinkedHashMap.entrySet().iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }
    
        }
    }
    
    

    结果

    1=1
    2=2
    3=3
    4=4
    5=5
    超出最大容量
    3=3
    4=4
    5=5
    1=1
    6=6
    
    Process finished with exit code 0
    
    

    根据上述结果可以看到,当超出最大容量时移除的是第二个结点,而不是第一个结点,因此一个简单的lru算法就实现了

    super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
    

    调用的是父类的

        public LinkedHashMap(int var1, float var2, boolean var3) {
            super(var1, var2);
            this.accessOrder = var3;
        }
    

    accessOrder为true表示会把最新访问的数据放到最后一个节点,默认false

  • 相关阅读:
    如何优雅地删除 Linux 中的垃圾文件
    session:
    cookie:
    多对多表结构设计:
    接口测试:
    oracle基本笔记整理
    oracle基本笔记整理
    oracle基本笔记整理
    2016年寒假心得
    2016年寒假心得
  • 原文地址:https://www.cnblogs.com/amberbar/p/11771273.html
Copyright © 2011-2022 走看看