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

  • 相关阅读:
    evernote100个做笔记的好方法
    平衡二叉树的调整模版
    晨间日记的奇迹
    hdu 2952 Counting Sheep
    hdu 1535 Invitation Cards
    poj 3259 Wormholes(spfa)
    poj 2263 Heavy Cargo(floyd)
    poj 3268 Silver Cow Party(SPFA)
    hdu 1690 Bus System
    hdu 3631 Shortest Path(Floyd)
  • 原文地址:https://www.cnblogs.com/amberbar/p/11771273.html
Copyright © 2011-2022 走看看