本文很有用
一、概念:
二、代码:
重写 linkedHashMap 实现了 lru
package com.heyjl.linkedhashmap_lru;
/**
* http://blog.youkuaiyun.com/yangpl_tale/article/details/44998365
* http://flychao88.iteye.com/blog/1977653
*
* LRU是一种淘汰策略,就是内存达到容量后,最近未使用的就扔掉,
* linkedHashMap 正常是不限量的不删除元素,
* 但是如果继承linkedHashMap,设置他的容量就可以LRU
* Created by jalo on 2017/11/9.
*/
import java.util.*;
//扩展一下LinkedHashMap这个类,让他实现LRU算法
class LRULinkedHashMap<K,V> extends LinkedHashMap<K,V>{
//定义缓存的容量
private int capacity;
private static final long serialVersionUID = 1L;
//带参数的构造器
LRULinkedHashMap(int capacity){
//调用LinkedHashMap的构造器,传入以下参数
super(16,0.75f,true);
//传入指定的缓存最大容量
this.capacity=capacity;
}
//实现LRU的关键方法,如果map里面的元素个数大于了缓存最大容量,则删除链表的顶端元素
@Override
public boolean removeEldestEntry(Map.Entry<K, V> eldest){
System.out.println(eldest.getKey() + "=" + eldest.getValue());
return size()>capacity;
}
}
//测试类
class LRU{
public static void main(String[] args) throws Exception{
//指定缓存最大容量为4
Map<Integer,Integer> map=new LRULinkedHashMap<Integer,Integer>(4);
map.put(9,3);
map.put(7,4);
map.put(5,9);
map.put(3,4);
map.put(6,6);
//总共put了5个元素,超过了指定的缓存最大容量
//遍历结果
for(Iterator<Map.Entry<Integer,Integer>> it=map.entrySet().iterator();it.hasNext();){
System.out.println(it.next().getKey());
}
}
}
三、redis 的置换策略:
当Redis内存使用达到maxmemory时,需要选择设置好的maxmemory-policy进行对老数据的置换。
下面是可以选择的置换策略:
- noeviction: 不进行置换,表示即使内存达到上限也不进行置换,所有能引起内存增加的命令都会返回error
- allkeys-lru: 优先删除掉最近最不经常使用的key,用以保存新数据
- volatile-lru: 只从设置失效(expire set)的key中选择最近最不经常使用的key进行删除,用以保存新数据
- allkeys-random: 随机从all-keys中选择一些key进行删除,用以保存新数据
- volatile-random: 只从设置失效(expire set)的key中,选择一些key进行删除,用以保存新数据
- volatile-ttl: 只从设置失效(expire set)的key中,选出存活时间(TTL)最短的key进行删除,用以保存新数据
选择合适的置换策略是很重要的,这主要取决于你的应用的访问模式,当然你也可以动态的修改置换策略,并通过用Redis命令——INFO去输出cache的命中率情况,进而可以对置换策略进行调优
一般来说,有这样一些常用的经验:
- 在所有的key都是最近最经常使用,那么就需要选择allkeys-lru进行置换最近最不经常使用的key,如果你不确定使用哪种策略,那么推荐使用allkeys-lru
- 如果所有的key的访问概率都是差不多的,那么可以选用allkeys-random策略去置换数据
- 如果对数据有足够的了解,能够为key指定hint(通过expire/ttl指定),那么可以选择volatile-ttl进行置换