正在显示
1 个修改的文件
包含
40 行增加
和
9 行删除
| @@ -15,6 +15,16 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; | @@ -15,6 +15,16 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; | ||
| 15 | /** | 15 | /** |
| 16 | * @author 子诚 | 16 | * @author 子诚 |
| 17 | * Description:自定义Redis作为mybatis二级缓存实现 | 17 | * Description:自定义Redis作为mybatis二级缓存实现 |
| 18 | + * 问题描述:缓存穿透、缓存雪崩 | ||
| 19 | + * <p> | ||
| 20 | + * 缓存穿透:就是说利用一些列措施,使得访问避开了缓存,直接访问数据库,使得数据库不堪重负引起的问题。比如(压测)访问数据库中不存在的数据 | ||
| 21 | + * 解决方案:读取数据库,不存在;依旧生成对应的key,放到缓存中,但是对应的value是null(mybatis的二级缓存是这样解决的)。 | ||
| 22 | + * 下次再次访问的话,就是读取缓存。 | ||
| 23 | + * <p> | ||
| 24 | + * 缓存雪崩:是指在某一特殊时刻,缓存中的缓存全部失效,然后这一时刻又有大量的数据库访问,导致数据库不堪重负。 | ||
| 25 | + * 解决方案:根据业务的不同设置不同的缓存失效时间。 | ||
| 26 | + * 比如:这个项目,做了3个namespace的缓存,其中一个namespace,共有5个Mapper指向它。所以选择使用范围内的随机值,来做缓存失效时间 | ||
| 27 | + * <p> | ||
| 18 | * 时间:2020/8/6 9:37 | 28 | * 时间:2020/8/6 9:37 |
| 19 | */ | 29 | */ |
| 20 | public class RedisCache implements Cache { | 30 | public class RedisCache implements Cache { |
| @@ -30,11 +40,6 @@ public class RedisCache implements Cache { | @@ -30,11 +40,6 @@ public class RedisCache implements Cache { | ||
| 30 | private static final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); | 40 | private static final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); |
| 31 | 41 | ||
| 32 | /** | 42 | /** |
| 33 | - * 缓存对象的是失效时间,30分钟 | ||
| 34 | - */ | ||
| 35 | - private static final long CACHE_TIME_IN_MINT = 30; | ||
| 36 | - | ||
| 37 | - /** | ||
| 38 | * 当前放入缓存的mapper的namespace | 43 | * 当前放入缓存的mapper的namespace |
| 39 | */ | 44 | */ |
| 40 | private final String id; | 45 | private final String id; |
| @@ -67,8 +72,34 @@ public class RedisCache implements Cache { | @@ -67,8 +72,34 @@ public class RedisCache implements Cache { | ||
| 67 | { | 72 | { |
| 68 | RedisTemplate redisTemplate = getRedisTemplate(); | 73 | RedisTemplate redisTemplate = getRedisTemplate(); |
| 69 | // 使用redis的hash类型作为缓存存储模型 | 74 | // 使用redis的hash类型作为缓存存储模型 |
| 70 | - redisTemplate.opsForHash().put(id.toString(), key.toString(), value); | ||
| 71 | - redisTemplate.expire(id.toString(), CACHE_TIME_IN_MINT, TimeUnit.MINUTES); | 75 | + redisTemplate.opsForHash().put(id.toString(), encryptionKey(key.toString()), value); |
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * 根据业务的不同,设置不同的缓存时间,解决掉缓存雪崩 | ||
| 79 | + */ | ||
| 80 | + if (id.equals("com.sunyo.wlpt.message.bus.service.mapper.VirtualHostMapper")) { | ||
| 81 | + // 设置缓存时间 | ||
| 82 | + redisTemplate.expire(id.toString(), random(1, 3), TimeUnit.HOURS); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + if (id.equals("com.sunyo.wlpt.message.bus.service.mapper.UserMessageBindingMapper")) { | ||
| 86 | + // 设置缓存时间 | ||
| 87 | + redisTemplate.expire(id.toString(), random(60, 100), TimeUnit.MINUTES); | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + if (id.equals("com.sunyo.wlpt.message.bus.service.mapper.UserInfoMapper")) { | ||
| 91 | + // 设置缓存时间 | ||
| 92 | + redisTemplate.expire(id.toString(), random(30, 50), TimeUnit.MINUTES); | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + /** | ||
| 97 | + * | ||
| 98 | + */ | ||
| 99 | + public int random(int low, int high) | ||
| 100 | + { | ||
| 101 | + int num = ((int) (Math.random() * (high - low))) + low; | ||
| 102 | + return num; | ||
| 72 | } | 103 | } |
| 73 | 104 | ||
| 74 | /** | 105 | /** |
| @@ -79,7 +110,7 @@ public class RedisCache implements Cache { | @@ -79,7 +110,7 @@ public class RedisCache implements Cache { | ||
| 79 | { | 110 | { |
| 80 | RedisTemplate redisTemplate = getRedisTemplate(); | 111 | RedisTemplate redisTemplate = getRedisTemplate(); |
| 81 | //根据key 从redis的hash类型中获取数据 | 112 | //根据key 从redis的hash类型中获取数据 |
| 82 | - return redisTemplate.opsForHash().get(id.toString(), key.toString()); | 113 | + return redisTemplate.opsForHash().get(id.toString(), encryptionKey(key.toString())); |
| 83 | } | 114 | } |
| 84 | 115 | ||
| 85 | /** | 116 | /** |
| @@ -133,7 +164,7 @@ public class RedisCache implements Cache { | @@ -133,7 +164,7 @@ public class RedisCache implements Cache { | ||
| 133 | /** | 164 | /** |
| 134 | * 封装一个对key进行md5处理方法 | 165 | * 封装一个对key进行md5处理方法 |
| 135 | */ | 166 | */ |
| 136 | - private String getKeyToMD5(String key) | 167 | + private String encryptionKey(String key) |
| 137 | { | 168 | { |
| 138 | return DigestUtils.md5DigestAsHex(key.getBytes()); | 169 | return DigestUtils.md5DigestAsHex(key.getBytes()); |
| 139 | } | 170 | } |
-
请 注册 或 登录 后发表评论