基于ConcurrentHashMap的缓存实现(key失效、key淘汰策略、value序列化解析实现)

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

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

private static final Integer CACHE_MAX_SIZE = 100000;

2、缓存(cacheMap):

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

注:MapCacheObj结构为:

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

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

private static final List<String> 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<UserDto> userDtos = ...;
String value = JSON.toJSONString(userDtos);
......
......
//反序列化
List<UserDto> 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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值