`
lxy2520
  • 浏览: 6052 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

基于LRU算法的缓存实现

 
阅读更多

基于LRU算法的缓存实现

林小应

1. 问题描述

业务系统中,可能会用到很多规格数据。如果每次都从数据库读取,开销是很大的。一次业务操作,可能会取几千次,甚至更多。如通信、银行、证券等系统的规则校验就是这样。

很多系统开始使用缓存机制,如memcached、redis。它们的性能都很好,但是都有一个序列化、反序列化的过程。一次反序列化开销可能是1ms。而对于规格数据,我们在应用程序中一般是不会修改的,所以我们不希望序列化、反序列化。

我们可以将这些规格数据存放在内存容器中,直接使用,速度非常快。但是不能全部放进来,那样可能会OutOfMemory。

so、我们希望在内存中存放最近最常用的一些规格数据。比如,存放最近最常用的1万条规格数据、并且一个小时不被使用的全部被剔除。

2. 期望

提高读取配置数据的速度,就像从内存读取一个常量一样。必须支持实时刷新,如果数据库里面的规格数据被修改了,可以在3s内反应到缓存,缓存做出对应的更新。

对于规格数据还支持分地区存放(如江苏的13个地市)、分模块存放(如产品、客户)。

3. 设计原理

我们以江苏省某系统为例、配置数据分为13个本地网(南京、镇江、扬州、常州、无锡、苏州……),简单说明一下具体思路。

给每个本地网建一个容器,这里是一个线程安全的HashMap。将最近访问到的配置数据包装成一个特殊对象(SVObject自检测对象)存入HashMap

HashMap中存放的对象包含一个属性“最后访问时间”,客户端每次访问该对象都会更新一下“最后访问时间”。

启动一个监控线程,不断扫描13个本地网的HashMap容器,发现有最后访问时间距离当前超过一小时的,就将其剔除。

另外,客户端从HashMap取数据时,需要先检验一下当前的缓存版本是否和容器中的数据使用的缓存版本相同。如果不相同,说明缓存版本有更新,就将原来的HashMap容器清空。重新建一个HashMap容器,替代原来的(这一步是很讲究的)。

客户端从HashMap容器中取到对象,就返回,如果没有取到,就去数据库读取,然后将读到的数据包装成SVObject,存入HashMap容器(如果容量小于一万)、返回。

数据存在形式:

4.用法示例

Object obj = SVCacheUtil.getCache(key,areaCode,version,cacheGetter);

其中 version是当前缓存版本,cacheGetter是缓存客户端对象,是不是很简单。

qq:346420558


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics