TOP K+LRU缓存刷新
2015-09-30 15:04
225 查看
本地缓存机制常被用来存储系统中变化频率不高的数据,常见的变化频率不高数据有:比如商品配置,可能商家的商品描述信息基本不变化,价格变化也不是很频繁,那可以存在缓存里减少访问数据库。又比如某类计算存在热数据,即某些问题的计算入参在短时间内频繁重,则可以把计算结果缓存起来。
设计了类似LRU+TOP K的思路,针对新来的请求先查缓存,若没有实时计算,并把结果添加到缓存,之后对缓存按照请求次数和最近访问时间排序(先按照时间由近到远,再按照请求次数由大到小,最终顺序为请求次数由大到小,次数相同的时间由近到远),每次更新后删除顺序值大于缓存SIZE的计算结果。
示例代码如下:
public class ComputeServiceWithCache {
/** 计算结果缓存MAP(用于查询) */
private volatile Map<String, ComputeResult> resultCacheMap = new HashMap<String, ComputeResult>();
/** 已排序缓存列表(用于排序,维护在内存中,提高排序效率) */
private List<ComputeResult> cacheRankList = new ArrayList<ComputeResult>();
/** 计算服务 */
private ComputeService computeService;
/** 缓存大小 */
private static final int CACHE_SIZE = 100;
/** 数值1 */
private static final int ONE = 1;
/**
* 计算买卖双方的关系
*
* @param buyerId 买家ID
* @param sellerId 卖家ID
* @return 计算结果
*/
public ComputeResult computeRelation(String buyerId, String sellerId) {
String cacheKey = buyerId + sellerId;
ComputeResult result = findRelationInCache(cacheKey);
if (null == result) {
result = computeService.compute(buyerId, sellerId);
addComputeResultToCache(result);
}
return result;
}
/**
* 添加缓存并对缓存按照访问次数和最近访问时间排序
*
* @param result 当前计算结果
*/
public synchronized void addComputeResultToCache(ComputeResult result) {
// 添加缓存
List<ComputeResult> cacheRankList = composeCacheRankList(result);
// 按照访问次数和最近访问时间对缓存排序
sortCache(cacheRankList);
resultCacheMap.put(result.getCacheKey(), result);
if (cacheRankList.size() >= CACHE_SIZE) {
ComputeResult lastRankResult = cacheRankList.get(cacheRankList.size() - 1);
resultCacheMap.remove(lastRankResult.getCacheKey());
}
}
/**
* 添加缓存
*
* @param result 当前计算结果
* @return cacheRankList 待排序缓存列表
*/
private List<ComputeResult> composeCacheRankList(ComputeResult result) {
result.setVisitCnt(ONE);
result.setVisitTime(new Date());
ComputeResult cachedResult = resultCacheMap.get(result.getCacheKey());
if (null != cachedResult) {
Integer currentVisitCnt = result.getVisitCnt() + ONE;
result.setVisitCnt(currentVisitCnt);
for (ComputeResult tempResult : cacheRankList) {
if (StringUtil.equals(tempResult.getCacheKey(), result.getCacheKey())) {
tempResult.setVisitCnt(currentVisitCnt);
}
}
} else {
cacheRankList.add(result);
}
return cacheRankList;
}
/**
* 按照访问次数和最近访问时间对缓存排序
* (先按照时间由近到远,再按照请求次数由大到小,最终顺序为请求次数由大到小,次数相同的时间由近到远)
* @param cacheRankList 待排序缓存列表
*/
private void sortCache(List<ComputeResult> cacheRankList) {
Collections.sort(cacheRankList, new Comparator<ComputeResult>() {
@Override
public int compare(ComputeResult left, ComputeResult right) {
return left.getVisitTime().after(right.getVisitTime()) ? -1 : 1;
}
});
Collections.sort(cacheRankList, new Comparator<ComputeResult>() {
@Override
public int compare(ComputeResult left, ComputeResult right) {
return left.getVisitCnt() - right.getVisitCnt();
}
});
}
private class ComputeResult {
/** 计算结果缓存key */
private String cacheKey;
/** 计算结果访问次数 */
private Integer visitCnt;
/** 计算结果最近访问时间 */
private Date visitTime;
/** 结果关系值 */
private Integer relationValue;
/**
* Getter method for property <tt>visitTime</tt>.
*
* @return property value of visitTime
*/
public Date getVisitTime() {
return visitTime;
}
/**
* Setter method for property <tt>visitTime</tt>.
*
* @param visitTime value to be assigned to property visitTime
*/
public void setVisitTime(Date visitTime) {
this.visitTime = visitTime;
}
/**
* Getter method for property <tt>cacheKey</tt>.
*
* @return property value of cacheKey
*/
public String getCacheKey() {
return cacheKey;
}
/**
* Setter method for property <tt>cacheKey</tt>.
*
* @param cacheKey value to be assigned to property cacheKey
*/
public void setCacheKey(String cacheKey) {
this.cacheKey = cacheKey;
}
/**
* Getter method for property <tt>visitCnt</tt>.
*
* @return property value of visitCnt
*/
public Integer getVisitCnt() {
return visitCnt;
}
/**
* Setter method for property <tt>visitCnt</tt>.
*
* @param visitCnt value to be assigned to property visitCnt
*/
public void setVisitCnt(Integer visitCnt) {
this.visitCnt = visitCnt;
}
/**
* Getter method for property <tt>relationValue</tt>.
*
* @return property value of relationValue
*/
public Integer getRelationValue() {
return relationValue;
}
/**
* Setter method for property <tt>relationValue</tt>.
*
* @param relationValue value to be assigned to property relationValue
*/
public void setRelationValue(Integer relationValue) {
this.relationValue = relationValue;
}
}
}
设计了类似LRU+TOP K的思路,针对新来的请求先查缓存,若没有实时计算,并把结果添加到缓存,之后对缓存按照请求次数和最近访问时间排序(先按照时间由近到远,再按照请求次数由大到小,最终顺序为请求次数由大到小,次数相同的时间由近到远),每次更新后删除顺序值大于缓存SIZE的计算结果。
示例代码如下:
public class ComputeServiceWithCache {
/** 计算结果缓存MAP(用于查询) */
private volatile Map<String, ComputeResult> resultCacheMap = new HashMap<String, ComputeResult>();
/** 已排序缓存列表(用于排序,维护在内存中,提高排序效率) */
private List<ComputeResult> cacheRankList = new ArrayList<ComputeResult>();
/** 计算服务 */
private ComputeService computeService;
/** 缓存大小 */
private static final int CACHE_SIZE = 100;
/** 数值1 */
private static final int ONE = 1;
/**
* 计算买卖双方的关系
*
* @param buyerId 买家ID
* @param sellerId 卖家ID
* @return 计算结果
*/
public ComputeResult computeRelation(String buyerId, String sellerId) {
String cacheKey = buyerId + sellerId;
ComputeResult result = findRelationInCache(cacheKey);
if (null == result) {
result = computeService.compute(buyerId, sellerId);
addComputeResultToCache(result);
}
return result;
}
/**
* 添加缓存并对缓存按照访问次数和最近访问时间排序
*
* @param result 当前计算结果
*/
public synchronized void addComputeResultToCache(ComputeResult result) {
// 添加缓存
List<ComputeResult> cacheRankList = composeCacheRankList(result);
// 按照访问次数和最近访问时间对缓存排序
sortCache(cacheRankList);
resultCacheMap.put(result.getCacheKey(), result);
if (cacheRankList.size() >= CACHE_SIZE) {
ComputeResult lastRankResult = cacheRankList.get(cacheRankList.size() - 1);
resultCacheMap.remove(lastRankResult.getCacheKey());
}
}
/**
* 添加缓存
*
* @param result 当前计算结果
* @return cacheRankList 待排序缓存列表
*/
private List<ComputeResult> composeCacheRankList(ComputeResult result) {
result.setVisitCnt(ONE);
result.setVisitTime(new Date());
ComputeResult cachedResult = resultCacheMap.get(result.getCacheKey());
if (null != cachedResult) {
Integer currentVisitCnt = result.getVisitCnt() + ONE;
result.setVisitCnt(currentVisitCnt);
for (ComputeResult tempResult : cacheRankList) {
if (StringUtil.equals(tempResult.getCacheKey(), result.getCacheKey())) {
tempResult.setVisitCnt(currentVisitCnt);
}
}
} else {
cacheRankList.add(result);
}
return cacheRankList;
}
/**
* 按照访问次数和最近访问时间对缓存排序
* (先按照时间由近到远,再按照请求次数由大到小,最终顺序为请求次数由大到小,次数相同的时间由近到远)
* @param cacheRankList 待排序缓存列表
*/
private void sortCache(List<ComputeResult> cacheRankList) {
Collections.sort(cacheRankList, new Comparator<ComputeResult>() {
@Override
public int compare(ComputeResult left, ComputeResult right) {
return left.getVisitTime().after(right.getVisitTime()) ? -1 : 1;
}
});
Collections.sort(cacheRankList, new Comparator<ComputeResult>() {
@Override
public int compare(ComputeResult left, ComputeResult right) {
return left.getVisitCnt() - right.getVisitCnt();
}
});
}
private class ComputeResult {
/** 计算结果缓存key */
private String cacheKey;
/** 计算结果访问次数 */
private Integer visitCnt;
/** 计算结果最近访问时间 */
private Date visitTime;
/** 结果关系值 */
private Integer relationValue;
/**
* Getter method for property <tt>visitTime</tt>.
*
* @return property value of visitTime
*/
public Date getVisitTime() {
return visitTime;
}
/**
* Setter method for property <tt>visitTime</tt>.
*
* @param visitTime value to be assigned to property visitTime
*/
public void setVisitTime(Date visitTime) {
this.visitTime = visitTime;
}
/**
* Getter method for property <tt>cacheKey</tt>.
*
* @return property value of cacheKey
*/
public String getCacheKey() {
return cacheKey;
}
/**
* Setter method for property <tt>cacheKey</tt>.
*
* @param cacheKey value to be assigned to property cacheKey
*/
public void setCacheKey(String cacheKey) {
this.cacheKey = cacheKey;
}
/**
* Getter method for property <tt>visitCnt</tt>.
*
* @return property value of visitCnt
*/
public Integer getVisitCnt() {
return visitCnt;
}
/**
* Setter method for property <tt>visitCnt</tt>.
*
* @param visitCnt value to be assigned to property visitCnt
*/
public void setVisitCnt(Integer visitCnt) {
this.visitCnt = visitCnt;
}
/**
* Getter method for property <tt>relationValue</tt>.
*
* @return property value of relationValue
*/
public Integer getRelationValue() {
return relationValue;
}
/**
* Setter method for property <tt>relationValue</tt>.
*
* @param relationValue value to be assigned to property relationValue
*/
public void setRelationValue(Integer relationValue) {
this.relationValue = relationValue;
}
}
}
相关文章推荐
- Hadoop框架排序和分组的理解
- (IIS8/8.5/Apache)301域名重定向
- linux mint安装搜狗输入法
- 给CentOS6.3 + PHP5.3 安装PHP性能测试工具 XHProf-0.9.2
- Open MPI的目标、概念及实现
- CentOS7网卡设置为桥接模式静态IP配置方法详解
- 浅析nginx刚刚发布的JavaScript能力nginScript
- linux下dns设置详解
- 基于LAMP 的NFS数据共享论坛网站 推荐
- Linux下查看文件内容的命令
- linux 用rpm安装GCC过程
- OpenGL教程翻译 第二十二课 使用Assimp加载模型
- Linux LVM磁盘空间扩容的新方法
- opengl中的三维数学一(基础三维讲解)
- linux Read命令
- OpenGL教程翻译 第二十一课 聚光灯
- tomcat环境变量配置
- linux常用命令(63):at命令
- Ubuntu 14下手动安装FireFox和chromium-browser的FlashPlayer 插件
- solr5.3.1在tomcat和jetty上安装方案