作者 王勇

完善mybatis的二级缓存

... ... @@ -15,6 +15,16 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author 子诚
* Description:自定义Redis作为mybatis二级缓存实现
* 问题描述:缓存穿透、缓存雪崩
* <p>
* 缓存穿透:就是说利用一些列措施,使得访问避开了缓存,直接访问数据库,使得数据库不堪重负引起的问题。比如(压测)访问数据库中不存在的数据
* 解决方案:读取数据库,不存在;依旧生成对应的key,放到缓存中,但是对应的value是null(mybatis的二级缓存是这样解决的)。
* 下次再次访问的话,就是读取缓存。
* <p>
* 缓存雪崩:是指在某一特殊时刻,缓存中的缓存全部失效,然后这一时刻又有大量的数据库访问,导致数据库不堪重负。
* 解决方案:根据业务的不同设置不同的缓存失效时间。
* 比如:这个项目,做了3个namespace的缓存,其中一个namespace,共有5个Mapper指向它。所以选择使用范围内的随机值,来做缓存失效时间
* <p>
* 时间:2020/8/6 9:37
*/
public class RedisCache implements Cache {
... ... @@ -30,11 +40,6 @@ public class RedisCache implements Cache {
private static final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
/**
* 缓存对象的是失效时间,30分钟
*/
private static final long CACHE_TIME_IN_MINT = 30;
/**
* 当前放入缓存的mapper的namespace
*/
private final String id;
... ... @@ -67,8 +72,34 @@ public class RedisCache implements Cache {
{
RedisTemplate redisTemplate = getRedisTemplate();
// 使用redis的hash类型作为缓存存储模型
redisTemplate.opsForHash().put(id.toString(), key.toString(), value);
redisTemplate.expire(id.toString(), CACHE_TIME_IN_MINT, TimeUnit.MINUTES);
redisTemplate.opsForHash().put(id.toString(), encryptionKey(key.toString()), value);
/**
* 根据业务的不同,设置不同的缓存时间,解决掉缓存雪崩
*/
if (id.equals("com.sunyo.wlpt.message.bus.service.mapper.VirtualHostMapper")) {
// 设置缓存时间
redisTemplate.expire(id.toString(), random(1, 3), TimeUnit.HOURS);
}
if (id.equals("com.sunyo.wlpt.message.bus.service.mapper.UserMessageBindingMapper")) {
// 设置缓存时间
redisTemplate.expire(id.toString(), random(60, 100), TimeUnit.MINUTES);
}
if (id.equals("com.sunyo.wlpt.message.bus.service.mapper.UserInfoMapper")) {
// 设置缓存时间
redisTemplate.expire(id.toString(), random(30, 50), TimeUnit.MINUTES);
}
}
/**
*
*/
public int random(int low, int high)
{
int num = ((int) (Math.random() * (high - low))) + low;
return num;
}
/**
... ... @@ -79,7 +110,7 @@ public class RedisCache implements Cache {
{
RedisTemplate redisTemplate = getRedisTemplate();
//根据key 从redis的hash类型中获取数据
return redisTemplate.opsForHash().get(id.toString(), key.toString());
return redisTemplate.opsForHash().get(id.toString(), encryptionKey(key.toString()));
}
/**
... ... @@ -133,7 +164,7 @@ public class RedisCache implements Cache {
/**
* 封装一个对key进行md5处理方法
*/
private String getKeyToMD5(String key)
private String encryptionKey(String key)
{
return DigestUtils.md5DigestAsHex(key.getBytes());
}
... ...