天天看点

fastjson 添加key value_基于ConcurrentHashMap的缓存实现(key失效、淘汰策略、序列化)问题场景:实现思路:

fastjson 添加key value_基于ConcurrentHashMap的缓存实现(key失效、淘汰策略、序列化)问题场景:实现思路:

问题场景:

缓存资源(如:Redis)稀缺,但是又希望用到缓存的情况。比如:通过Rpc接口获取的城市的信息(城市ID、名等,数据变动频率很低)、数据库配置的数据(如果用Apollo、Nacos配置中心的就没必要了)、数据库计算的topN数据(业务需要,但是,不能频繁计算)。

实现思路:

1、缓存最大个数(cachMaxSize):机器的内存资源也是有限的,所以,需要限制ConcurrentHashMap占用的内存空间。

private static final Integer CACHE_MAX_SIZE = 100000;
           

2、缓存(cacheMap):

private static final Map cacheMap = new ConcurrentHashMap<>();
           

注:MapCacheObj结构为:

//缓存对象
           
private Object CacheValue;
           
//缓存过期时间
           
private long ttlTime;
           
}
           

3、缓存使用记录(cacheLogList):

如果key如果被获取过,那么,记录一次使用记录,节点插入到链表到最前面(注:插入前需要遍历删除已经存在的同名到key,这样在做淘汰策略时,只需要删除尾部的节点对应的key即可)(注:此处数据结构如果该用数组将更高效)。

private static final List CACHE_LOG_LIST = new LinkedList<>();
           

4、守护线程(辅助删除过期key,在获取key的时候还会做一次是否过期的校验):

开启一个线程,定时扫描key超时信息,并删除过期的key。

5、Key失效:

每次获取key的时候,都需要做一次时间是否过期判断,如果过期了,那么就返回空,同时删除掉key(注:守护线程也起到一定到辅助作用)。

6、最近未使用(lastest unused):

根据缓存使用记录cacheLogList来判断,链表末尾的就是最久未使用的,优先淘汰删除。

7、Key、Value的序列化(fastjson):

例如:存储的时用户信息的List,那么,将list转为JSONString做为value存储。

获取的时候,解析方式:JSON.parseArray((String)object, UserDto.class);(注意:小技巧:key的命名单独定义在一个类中几种管理,如果时List那么在命名的尾部做标示,这样解析的时候就明确用JSON.parseArray还是JSON.parse)

//将用户信息list序列化为json string
           
List userDtos = ...;
           
String value = JSON.toJSONString(userDtos);
           
......
           
......
           
//反序列化
           
List userDtoList = JSON.parseArray((String)value, RingTypeTreeDto.class);
           

代码实现:

https://github.com/sijunx/mySpider/blob/feature_word_dic_20191001001/spider-base/spider-base-utils/src/main/java/com/spider/base/utils/MapCacheUtils.java