缓存的策略有很多,在应用系统中可根据情况 选择,通常会把一些 静态数据后者变化频率不高的数据放到缓存中,如配置参数、字典表等。而有些场景可能要寻找替代方案,比如,想提升全文检索的速度,在复杂场景下建议使用搜索引擎,如Solr或 ElasticSearch。
通常在Web开发中,不同层级对应的缓存要求和缓存策略全然不同,如下图:
下面了解一下缓存中的两个比较重要的基本概念:
1. 缓存命中率
即从缓存中读取数据的次数与总读取次数的比率。一般来说,命中率越高越好。
命中率 = 从缓存中读取的次数 /(总读取次数【从缓存中读取的次数 + 从慢速设备上读取的次数】)
Miss 率 = 没有从缓存中读取的次数 /(总读取次数[从缓存中读取的次数 + 从慢速设备上读取的次数])
如果要做缓存,就一定要监控这个指标,来看缓存是否工作良好。
2.过期策略
首先自定义一个User实体类。
public class User implements Serializable { private String userId; private String userName; private int age; public User(String userId) { this.userId = userId; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
接下来定义一个缓存管理器:
public class CacheManager<T> { private Map<String, T> cache = new ConcurrentHashMap<String, T>(); public T getValue(Object key) { return cache.get(key); } public void addOrUpdate(String key, T value) { cache.put(key, value); } public void delCache(String key) { if (cache.containsKey(key)) { cache.remove(key); } } public void clearCache() { cache.clear(); } }
提供用户查询的服务类,此服务类使用缓存管理器来支持用户查询。
public class UserService { private CacheManager<User> cacheManager; public UserService() { cacheManager = new CacheManager<User>(); } @Cacheable(cacheNames = "users") public User getUserById(String userId) { // 方法内部实现不考虑缓存逻辑,直接实现业务 System.out.println("read quert user. " + userId); return getFromDB(userId); } public void reload() { cacheManager.clearCache(); } private User getFromDB(String userId) { return new User(userId); } }
使用SpringCache 来实现上面的例子:
public class UserServiceUseSpringCache { private CacheManager<User> cacheManager; public UserServiceUseSpringCache() { cacheManager = new CacheManager<User>(); } public User getUserById(String userId) { User result = cacheManager.getValue(userId); if (result != null) { System.out.println("get from cache..." + userId); // 如果在缓存中,则直接返回缓存的结果 return result; } // 否则从数据库查询 result = getFromDB(userId); if (result != null) { // 将数据库查询的结果更新到缓存中 cacheManager.addOrUpdate(userId, result); } return result; } public void reload() { cacheManager.clearCache(); } private User getFromDB(String userId) { return new User(userId); } }
现在还需要一个Spring 配置文件来支持基于注解的缓存:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> <!-- 启动基于注解的缓存驱动 这个配置项默认使用了一个定义为cacheManager的缓存管理器。 --> <cache:annotation-driven /> <bean id="accountServiceBean" class="cacheOfAnno.AccountService"/> <!-- generic cache manager --> <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager"> <property name="caches"> <set> <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="default" /> <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="users" /> </set> </property> </bean> </beans>
上面在UserService代码中没有看到任何缓存逻辑代码,只需一个注解@Cacheable(cacheNames="users"),就实现了基本的缓存方案,代码变得非常优雅、简洁。使用Spring Cache 只需完成以下两个步骤:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。