《springcache抽象详解》由会员分享,可在线阅读,更多相关《springcache抽象详解(18页珍藏版)》请在金锄头文库上搜索。
1、SpringCache抽象详解缓存简介缓存,我的理解是:让数据更接近于使用者;工作机制是:先从缓存中读取数据,如果没有再从慢速设备上读取实际数据(数据也会存入缓存);缓存什么:那些经常读取且不经常修改的数据/那些昂贵(CPU/IO)的且对于相同的请求有相同的计算结果的数据。如CPU-L1/L2-内存-磁盘就是一个典型的例子,CPU需要数据时先从L1/L2中读取,如果没有到内存中找,如果还没有会到磁盘上找。还有如用过Maven的朋友都应该知道,我们找依赖的时候,先从本机仓库找,再从本地服务器仓库找,最后到远程仓库服务器找;还有如京东的物流为什么那么快?他们在各个地都有分仓库,如果该仓库有货物那么
2、送货的速度是非常快的。缓存命中率即从缓存中读取数据的次数与总读取次数的比率,命中率越高越好:命中率=从缓存中读取次数/(总读取次数从缓存中读取次数+从慢速设备上读取的次数)Miss率=没有从缓存中读取的次数/(总读取次数从缓存中读取次数+从慢速设备上读取的次数)这是一个非常重要的监控指标,如果做缓存一定要健康这个指标来看缓存是否工作良好;缓存策略Evictionpolicy移除策略,即如果缓存满了,从缓存中移除数据的策略;常见的有LFU、LRU、FIFO:FIFO(FirstInFirstOut):先进先出算法,即先放入缓存的先被移除;LRU(LeastRecentlyUsed):最久未使用算
3、法,使用时间距离现在最久的那个被移除;LFU(LeastFrequentlyUsed):最近最少使用算法,一定时间段内使用次数(频率)最少的那个被移除;TTL(TimeToLive)存活期,即从缓存中创建时间点开始直到它到期的一个时间段(不管在这个时间段内有没有访问都将过期)TTI(TimeToIdle)空闲期,即一个数据多久没被访问将从缓存中移除的时间。到此,基本了解了缓存的知识,在Java中,我们一般对调用方法进行缓存控制,比如我调用findUserById(Longid),那么我应该在调用这个方法之前先从缓存中查找有没有,如果没有再掉该方法如从数据库加载用户,然后添加到缓存中,下次调用时
4、将会从缓存中获取到数据。自Spring3.1起,提供了类似于Transactional注解事务的注解Cache支持,且提供了Cache抽象;在此之前一般通过AOP实现;使用SpringCache的好处:提供基本的Cache抽象,方便切换各种底层Cache;通过注解Cache可以实现类似于事务一样,缓存逻辑透明的应用到我们的业务代码上,且只需要更少的代码就可以完成;提供事务回滚时也自动回滚缓存;支持比较复杂的缓存逻辑;对于SpringCache抽象,主要从以下几个方面学习:CacheAPI及默认提供的实现Cache注解实现复杂的Cache逻辑CacheAPI及默认提供的实现Spring提供的核心
5、Cache接口:Java代码packageorg.springframework.cache;publicinterfaceCacheStringgetName();/缓存的名字ObjectgetNativeCache();/得到底层使用的缓存,如EhcacheValueWrapperget(Objectkey);/根据key得到一个ValueWrapper,然后调用其get方法获取值<T>Tget(Objectkey,Class<T>type);/根据key,和value的类型直接获取valuevoidput(Objectkey,Objectvalue);/往缓存放数
6、据voidevict(Objectkey);/从缓存中移除key对应的缓存voidclear();/清空缓存interfaceValueWrapper/缓存值的WrapperObjectget();/得到真实的value提供了缓存操作的读取/写入/移除方法;默认提供了如下实现:ConcurrentMapCache:使用java.util.concurrent.ConcurrentHashMap实现的Cache;mon.cache.Cache进行的Wrapper,需要GoogleGuava12.0或更高版本,sincespring4;EhCacheCache:使用Ehcache实现JCacheC
7、ache:对javax.cache.Cache进行的wrapper,sincespring3.2;spring4将此类更新到JCache0.11版本;另外,因为我们在应用中并不是使用一个Cache,而是多个,因此Spring还提供了CacheManager抽象,用于缓存的管理:Java代码packageorg.springframework.cache;importjava.util.Collection;publicinterfaceCacheManagerCachegetCache(Stringname);/根据Cache名字获取CacheCollection<String>g
8、etCacheNames();/得到所有Cache的名字默认提供的实现:ConcurrentMapCacheManager/ConcurrentMapCacheFactoryBean:管理ConcurrentMapCache;GuavaCacheManager;EhCacheCacheManager/EhCacheManagerFactoryBeanJCacheCacheManager/JCacheManagerFactoryBean另外还提供了CompositeCacheManager用于组合CacheManager,即可以从多个CacheManager中轮询得到相应的Cache,如Java
9、代码<beanid=cacheManagerclass=org.springframework.cache.support.CompositeCacheManager><propertyname=cacheManagers><list><refbean=ehcacheManager/><refbean=jcacheManager/></list></property><propertyname=fallbackToNoOpCachevalue=true/></bean>当我们调用cach
10、eManager.getCache(cacheName)时,会先从第一个cacheManager中查找有没有cacheName的cache,如果没有接着查找第二个,如果最后找不到,因为fallbackToNoOpCache=true,那么将返回一个NOP的Cache否则返回null。除了GuavaCacheManager之外,其他Cache都支持Spring事务的,即如果事务回滚了,Cache的数据也会移除掉。Spring不进行Cache的缓存策略的维护,这些都是由底层Cache自己实现,Spring只是提供了一个Wrapper,提供一套对外一致的API。示例需要添加Ehcache依赖,具体依
11、赖轻参考pom.xmlSpringCacheTest.javaJava代码Testpublicvoidtest()throwsIOException/创建底层Cachenet.sf.ehcache.CacheManagerehcacheManager=newnet.sf.ehcache.CacheManager(newClassPathResource(ehcache.xml).getInputStream();/创建Spring的CacheManagerEhCacheCacheManagercacheCacheManager=newEhCacheCacheManager();/设置底层的Ca
12、cheManagercacheCacheManager.setCacheManager(ehcacheManager);Longid=1L;Useruser=newUser(id,zhang,);/根据缓存名字获取CacheCachecache=cacheCacheManager.getCache(user);/往缓存写数据cache.put(id,user);/从缓存读数据Assert.assertNotNull(cache.get(id,User.class);此处直接使用Spring提供的API进行操作;我们也可以通过xml/注解方式配置到spring容器;xml风格的(spring-c
13、ache.xml):Java代码<beanid=ehcacheManagerclass=org.springframework.cache.ehcache.EhCacheManagerFactoryBean><propertyname=configLocationvalue=classpath:ehcache.xml/></bean><beanid=cacheManagerclass=org.springframework.cache.ehcache.EhCacheCacheManager><propertyname=cacheManage
14、rref=ehcacheManager/><propertyname=transactionAwarevalue=true/></bean>spring提供EhCacheManagerFactoryBean来简化ehcachecacheManager的创建,这样注入configLocation,会自动根据路径从classpath下找,比编码方式简单多了,然后就可以从spring容器获取cacheManager进行操作了。此处的transactionAware表示是否事务环绕的,如果true,则如果事务回滚,缓存也回滚,默认false注解风格的(AppConfig.
15、java):Java代码BeanpublicCacheManagercacheManager()trynet.sf.ehcache.CacheManagerehcacheCacheManager=newnet.sf.ehcache.CacheManager(newClassPathResource(ehcache.xml).getInputStream();EhCacheCacheManagercacheCacheManager=newEhCacheCacheManager(ehcacheCacheManager);returncacheCacheManager;catch(IOExceptione)thrownewRuntimeException(e);和编程方式差不多就不多介绍了。另外