缓存是高并发程序开发中的一大利器,利用缓存我们能够显著有效的提高程序的响应能力,缓存服务器和数据库的压力,市面上常用的缓存有单机缓存memcached,集群缓存redis等等,
对于大型互联网项目的高并发场景我们使用第三方缓存插件是首选,但是对于一些并发不是很大,但是频繁访问数据库也会影响性能和带来压力的一些场景,我们可以是用本地缓存来
提高程序响应速度和缓解服务器和数据可压力,常用的本地缓存有guava的本地cache,以及各个公司自己封装的本地缓存插件(本质上本地缓存是使用Map实现的,差别在于实现方式和性能)
,此篇就使用guava实现本地缓存展开叙述:
一、新建maven项目&添加依赖
新建一个通用的maven工程,并添加一下guava依赖:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
二、实现本地缓存
我们借助guava的本地缓存并对其封装,实现我们的本地缓存操作工具类,实现方式如下:
package com.typhoon.demo1.cache;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.builder.ToStringBuilder;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
/**
* guava本地缓存工具类
*
* @author Typhoon
* @date 2017-05-24 15:48
* @since V2.0
*/
public abstract class LocalCacheUtil {
// private static final Logger LOGGER =
// LoggerFactory.getLogger(LocalCacheUtil.class);
private static Cache<Object, Object> cache = CacheBuilder.newBuilder().maximumSize(100)
.expireAfterWrite(24, TimeUnit.HOURS).recordStats().build();
/**
* 放入本地缓存
*
* @author Typhoon
* @date 2017-05-24 16:34
* @since V2.0
* @param key
* @param value
*/
public static void put(Object key, Object value) {
if (null == key) {
throw new IllegalArgumentException("key can not be null");
}
cache.put(key, value);
}
/**
* 根据key获取value
*
* @author Typhoon
* @date 2017-05-24 15:51
* @since V2.0
* @description
* <ul>
* <li>如果key存在返回对应value</li>
* <li>如果key不存在返回null</li>
* <li>注*:cache.get(key,Callable
* <Object>)不允许key不存在的情况,但是实际情况下是允许的,需要外层捕获异常</li>
* </ul>
* @param key
* @return <code>Object</code>
*/
public static Object get(Object key) {
if (null == key) {
throw new IllegalArgumentException("key can not be null");
}
return cache.getIfPresent(key);
}
/**
* <ul>
* <li>根据key获取value,如果获取为null,根据传入的callable使用其他方式获取</li>
* <li>如果穿进来callable为null,调用<method>get(key)</method></li>
* </ul>
*
* @author Typhoon
* @date 2017-05-24 16:07
* @since V2.0
* @param key
* @param callable
* @return <result>Object</result>
*/
public static Object get(Object key, Callable<? extends Object> callable) {
if (null == key) {
throw new IllegalArgumentException("key can not be null");
}
if (null == callable) {
return get(key);
}
Object value = null;
try {
value = cache.get(key, callable);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
/**
* 失效某个key
*
* @author Typhoon
* @date 2017-05-24 16:09
* @since V2.0
* @param key
*/
public static void invalidateKey(Object key) {
if (null == key) {
throw new IllegalArgumentException("key can not be null");
}
cache.invalidate(key);
}
/**
* 失效某个key集
*
* @author Typhoon
* @date 2017-05-24 16:09
* @since V2.0
* @param keys
*/
public static void invalidateKeys(List<Object> keys) {
if (null == keys || keys.size() == 0) {
throw new IllegalArgumentException("keys can not be empty");
}
cache.invalidateAll(keys);
}
}
分析:
注意:如果callable没有传就是用上一个方法get
三、测试本地缓存
编写单元测试类并测试本地缓存:
package com.typhoon.demo1.consumer;
import java.util.concurrent.Callable;
import org.apache.commons.lang3.builder.ToStringBuilder;
import com.typhoon.demo1.cache.LocalCacheUtil;
import com.typhoon.demo1.dao.UserDao;
import com.typhoon.demo1.entity.User;
public class LocalCacheConsumer {
public static void main(String[] args) {
final Long id = 1L;
String key = "user:id" + id;
Object obj = LocalCacheUtil.get(key, new Callable<User>() {
public User call() throws Exception {
// TODO Auto-generated method stub
return new UserDao().getUserById(id);
}
});
System.out.println(ToStringBuilder.reflectionToString(obj));
}
}
我们只测试一个方法,上述代码中可以发现,调用得失get(key,callable)方法,
如果本地缓存中根据key查不到数据,会使用callable中的new UserDao().getUserById(id)去数据库查询并返回结果,
运行单元测试方法,可以看到如下结果:
可以看到,我们已经拿到想要的结果.
总结
在有些场景下我们使用本地缓存更加方便和轻量级,但是任何一种事物都有其双面性,我们可以分析出本地缓存的优缺点:
ps:原创不易,多多支持!
本文分享自 PersistentCoder 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!