一.缓存的简单模拟实现代码
1>没有缓存时的代码java
public User findById(Integer id){ String sql="SELECT * FROM T_USER WHERE id=?"; return DBHelp.executeQueryForObject(User.class,sql,id); }
2>加上缓存后的代码web
public User findById(Integer id){ /**首先去缓存中查找对象,有就直接返回; 没有在去数据库中操做,而且把操做后的结果放入缓存中,方便后续的使用 */ User user = cache.get("user"+id); if(user==null){ String sql="SELECT * FROM T_USER WHERE id=?"; return DBHelp.executeQueryForObject(User.class,sql,id); cache.set("user"+id,user); } return user; }
3>cache的简单模拟实现算法
缓存的原理:缓存的内部实现是一个Map,Map<key,Object>中的key通常是具备标示性的给定,如user:0-->new User.
另外,缓存会基于指定的淘汰策略机制,决定数据的保留或移除.常见的缓存淘汰策略有三种:
1.基于数量
1.1 FIFO(first in first out):先进先出
弊端:若先出去的正好是常常要被请求的操做,这样会大大影响效率
1.2 LRU:最近最长被使用
1.3 JVM
1.4 ...
2.基于时间
3.基于数量+时间
具体说明以下:
当缓存须要被清理时(好比空间占用已经接近临界值了),须要使用某种淘汰算法来决定清理掉哪些数据。经常使用的淘汰算法有下面几种:
FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。
LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。
LFU:Least Frequently Used,最不常常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。sql
public class SimpleCache{ //HashTable是线程安全的,且不容许有null的key private static Map<String,Object> cache = new HashTable<>(); /**取值,从缓存里获取数据,叫命中缓存*/ public static Object getObject(String key){ //判断缓存中是否包含key,包含返回映射值;不包含返回null if(map.containsKey(key)){ return cache.get(key); } return null; } //放值 public static void setObject(String key,Object obj){ cache.put(key,obj); } //删除指定值并返回 publlic static Object removeObject(String key){ return cache.remove(key); } }
经常使用缓存的开源框架:EHCACHE
通常的缓存都是本地缓存.
分布式缓存 Redis , Memcached
问题:若查询的是单个结果集,能够直接去缓存中取值;但若是请求操做的结果集是一个集合,如List
则要进行缓存的时时刷新,以获取最新的结果.如论坛中,不少人在同一时间段内发帖,后台就必须不断的作insert/update/delete操做,操做完后,应该把原先放在缓存中的数据删除,这样,当用户刷新时,获取的是最新的数据,而不是缓存中没有更新的数据.
分布式缓存能够配置多台主机用于缓存,组成一个集群,这样当一台设备遇到故障后,能够将任务分摊到集群中的其余设备上,不影响正常运行.
---
EHCACHE的使用:
在MAVEN中配置EHCACHE的依赖:ehcache.xml(必需要叫这个名)
<ehcache> <diskStore path="java.io.tmpdir" /> <!--java.io.tmpdir为系统常量,表示当前用户下的临时文件夹--> <defaultCache maxElementInMemory="1000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" /> <cache name="users" maxElementInMemory="1000" eternal="false" <!--表示是否永久存储,若是为true,将致使下面两个参数无效--> timeToIdleSeconds="120"//闲置时间(最后访问时间-当前时间) timeToLiveSeconds="120"//存活时间(当前时间-建立时间,闲置时间<=存活时间) overflowToDisk="true"// <ehcache/>
EhCacheUtil.java缓存
import net.sf.ehcache.CacheManager; import net.sf.ehcache.Ehcache; import net.sf.ehcache.Element; public class EhCacheUtil{ private static CacheManager cacheManager = new CacheManager(); public static void set(String key,Object value){ Ehcache ehcache = cacheManager.getEhcache("myCache"); Element element = new Element(key,value); ehcace.put(element); } public static Object get(String key){ Ehcache ehcache = cacheManager.getEhcache("myCache"); Element element = ehcache.get(key); if(element!=null){ return element.getObjectValue(); } return null; } public static void remove(String key){ Ehcache ehcache = cacheManager.getEhcache("myCache"); ehcache.remove(key); } }
测试代码:安全
public class TestDao{ private Logger logger = LoggerFactory.getLogger(TestDao.class); //查询单个结果 public Message findById(Integer id){ Message message = (Message)EhCacheUtil.get("Message:"+id); if(message == null){ String sql = "select * from t_message where id=?"; message = DBHelp.query(sql,new BeanHandler<>(Message.class,id)); EhCacheUtil.set("Message:"+id,message); }else{ logger.debug("load message from cache"); } return message; } //查询多个结果(须要手动的刷新缓存) public List<Message> findAll(){ List<Message> messageList = EHCacheUtil.get("messageList"); if(messageList == null){ String sql = "select * from t_message order by id desc"; messageList = DBHelp.query(sql,new BeanListHandler<>(Message.class)); EhCacheUtil.set("messageList",messageList); } return messageList; } //新增数据 public void save(Message message){ String sql = "insert into t_message(message,author) values(?,?)"; DBHelp.update(sql,message.getMessage,message.getAuthor); //删除缓存中已有的集合 EhCacheUtil.remove("messageList"); } public static void main(String[] args){ TestDao testDao = new TestDao(); List<Message> messgeList = testDao.findAll();//from DB //messageList = testDao.findAll();from cache //中间作了insert操做 Message message = new Message("你妹","王宏"); testDao.save(message);//insert removeCache messageList = testDao.findAll();from DB messageList = testDao.findAll();from cache //使用断言 Assert.assertEquals(25,messageList.size()); } }