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

基于hibernate二级缓存的论坛缓存方案

阅读更多
前言
hibernate查询缓存很难用,更新某个实体后会导致与此实体相关的所有查询缓存失效,很不爽;
此方案建立在hibernate二级缓存的基础上
目的
缓存帖子的每一页(即回帖)
何时写缓存?何时清理缓存?
读取帖子第N页是缓存之,有回帖 修改回帖 删除回帖时清理缓存
缓存结构
/**
	 * 帖子分页缓存。
	 * cache key为帖子id;
	 * cache value为Map,key为页号; value为post id串,如‘2#3#4#5’
	 */
	private static Map<Integer, Map<Integer, String>> threadPostCache = new LRULinkedHashMap<Integer, Map<Integer, String>>(10000);


外层map以帖子id为主键,内层map以页号为主键,内层map的value为回帖id串 如‘2#3#4#5’
外层Map采用LRULinkedHashMap

真正的回帖数据在hibernate二级缓存中,下面是读取二级缓存的逻辑代码

	@Override
	public Page<ThreadPost> getPage(int pageNo, int pageSize, Integer postNum, Integer threadId) {
		pageNo = pageNo == 0 ? 1 : pageNo;
		Page<ThreadPost> page = null;
		
		Map<Integer, String> pageMap = threadPostCache.get(threadId);
		if(pageMap == null){
			pageMap = new HashMap<Integer, String>();
		}
		
		String postIdString = pageMap.get(pageNo);
		if(postIdString == null){
			//从数据库中加载Page
			page = threadPostManager.getPage(pageNo, pageSize, postNum, threadId);
			//生成postIdString 
			postIdString = joinPostId(page.getDataSet());
			pageMap.put(pageNo, postIdString);
			threadPostCache.put(threadId, pageMap);
		}else{
			page = buildPage(pageNo, pageSize, postNum, postIdString);
		}
		return page;
	}


//构造一个Page对象
	private Page<ThreadPost> buildPage(int pageNo, int pageSize, Integer postNum, String postIdString){
		if(StringUtils.isBlank(postIdString)){
			return Page.EMPTY_PAGE;
		}
		
		List<ThreadPost> list = new ArrayList<ThreadPost>(postIdString.length());
		for(String postId : postIdString.split("#")){
//[color=red]从hibernate二级缓存中读取[/color]
			list.add(threadPostManager.get(Integer.valueOf(postId)));
		}
		
		return new Page<ThreadPost>(pageNo, postNum, pageSize, list);
	}
分享到:
评论
6 楼 yzzh9 2009-12-02  
很好的方法,可以直接用到二级缓存。
5 楼 maike 2009-10-15  
dingyuan 写道
hibernate的查询缓存缓存的是查询列表的id,只有在删除和插入操作时才会失效,更新操作只会更新对象缓存,查询缓存是不会失效的


想问下,更新某一个对象后是更新缓存中的所有对象还是只更新缓存中的这个对象? 谢谢!
4 楼 dingyuan 2009-09-22  
hibernate的查询缓存缓存的是查询列表的id,只有在删除和插入操作时才会失效,更新操作只会更新对象缓存,查询缓存是不会失效的
3 楼 xly_971223 2009-09-22  
qchong 写道
注意线程同步。。。

说的极是
2 楼 qchong 2009-09-22  
注意线程同步。。。
1 楼 dizdev 2009-09-09  
great!

我觉得是个非常适中的解决办法。

您的策率似乎是 当有新回帖的时候发一次SQL并更新缓存。 但是我思考中,论坛的高频率回复会否导致缓存刷新太频繁而失去意义。转而言之,虽然分页大大缓解SQL压力,但是频繁的访问同样迫切的要求有缓存存在。

因此牺牲一点点实时效率换取运行效率的方案比较Fit成本

相关推荐

Global site tag (gtag.js) - Google Analytics