本地缓存,Redis缓存,数据库DB查询(结合代码分析)
问题背景
为什么要使用缓存?本地缓存/Redis缓存/数据库查询优先级?
一、为什么要使用缓存
原因:CPU的速度远远高于磁盘IO的速度
问题:很多信息存在数据库当中的,每次查询数据库就是一次IO操作
所以,提高响应速度,必须减少磁盘IO的操作,缓存就是为了提升系统性能而存在的
二、查询的优先级
1、本地缓存
2、Redis缓存
3、数据库查询
1 public static List<Content> getContentList(int positionId, String provCode, String areaCode) throws SQLException { 2 String key_p_p_a = positionId + "_" + provCode + "_" + areaCode; 3 List<Content> contentList = null; 4 String strTemp = "|"; 5 StringBuilder cacheLogInfoSb = new StringBuilder("get cache ["); 6 /*判断本地缓存是否存在*/ 7 if (ContentService.MAP_CONTENT_P_P_A.containsKey(key_p_p_a)) { 8 contentList = ContentService.MAP_CONTENT_P_P_A.get(key_p_p_a); 9 cacheLogInfoSb.append(strTemp).append(" by cache MAP_CONTENT_P_P_A get List, key:").append(key_p_p_a) 10 .append(",List.size:").append(contentList.size()); 11 /*判断Reids缓存是否存在*/ 12 }else if (RedisCached.has(key_p_p_a)) { 13 contentList = (List<Content>) RedisCached.get(key_p_p_a.getBytes()); 14 cacheLogInfoSb.append(strTemp).append(" by xmemcache MAP_CONTENT_P_P_A get List, key:").append(key_p_p_a) 15 .append(",List.size:").append(contentList.size()); 16 /*数据库查询操作*/ 17 } else { 18 try { 19 contentList = dao.getContentList(positionId, provCode, areaCode); 20 cacheLogInfoSb = new StringBuilder(" cache is not exists,get data by database"); 21 } catch (SQLException e) { 22 cacheLogInfoSb.append(strTemp).append("SQLException:").append(e.toString()); 23 e.printStackTrace(); 24 throw e; 25 } 26 log.info(cacheLogInfoSb.toString() + "]"); 27 log.info("[ContentService]加入缓存key_p_p_a, key:{},contentList.size:{}", key_p_p_a, contentList.size()); 28 /*数据库查询后,将结果写入redis,方便下次查询*/ 29 RedisCached.set(key_p_p_a, contentList, ContentService.Cache_ExPireTime_Day); 30 } 31 32 return contentList; 33 }
三、缓存常用的集合框架以及操作(实际使用得比较多的方法)
使用的MAP集合ConcurrentHashMap
1 public static Map<String, List<Content>> MAP_CONTENT_P_P_A = new ConcurrentHashMap<String, List<Content>>();
读取本地缓存get()
1 List<Content> list = ContentService.MAP_CONTENT_P_P_A.get(key);
设置本地缓存put()
1 ContentService.MAP_CONTENT_P_P_A.put(key_p_p_a, contentList);
定时更新本地/Redis缓存(代码演示)
1 /** 查询数据库,获取最新数据 **/ 2 Map<String, List<Content>> position_content_map_p_p_a = dao.queryContentListRelateProvCodeAreaCode(positionId); 3 /** 清除本地缓存 **/ 4 Iterator<String> contentskeysIterPPA = MAP_CONTENT_P_P_A.keySet().iterator(); 5 while (contentskeysIterPPA.hasNext()) { 6 String key = contentskeysIterPPA.next(); 7 if (key.startsWith(String.valueOf(positionId))) { 8 removeKeys.add(key); 9 } 10 } 11 /** 清除Redis缓存 **/ 12 for (int i = 0; i < removeKeys.size(); i++) { 13 String key = removeKeys.get(i); 14 contentList.addAll(MAP_CONTENT_P_P_A.remove(key)); 15 RedisCached.delete(key); 16 } 17 removeKeys.clear(); 18 /** 把最新内容加入MAP_CONTENT_P_P_A缓存 **/ 19 Iterator<String> keysIterppa = position_content_map_p_p_a.keySet().iterator(); 20 while (keysIterppa.hasNext()) { 21 String key = keysIterppa.next(); 22 reFreshContenList.addAll(position_content_map_p_p_a.get(key)); 23 MAP_CONTENT_P_P_A.putAll(position_content_map_p_p_a); 24 }