一身报国有万死,双鬓向人无再青。 —— 陆游
封装了一个操作redis
的管理层,简单处理了缓存穿透、击穿、雪崩问题
Manager
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package com.ruben.manager;
import com.alibaba.fastjson.TypeReference;
import java.util.function.Supplier;
public interface RedisManager {
<T> T getFromRedisOrPutIntoMysql(String key, Supplier<T> mysqlSupplier, TypeReference<T> typeReference); }
|
实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| package com.ruben.manager;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; import com.ruben.utils.Opt; import org.apache.commons.lang3.StringUtils; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import java.security.SecureRandom; import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.function.Supplier;
@Service public class RedisManagerImpl implements RedisManager {
public static final SecureRandom SECURE_RANDOM = new SecureRandom();
public static final int EXPIRE_SECONDS = 5 * 60 * 1000;
@Resource private StringRedisTemplate stringRedisTemplate;
@Override @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED, isolation = Isolation.READ_UNCOMMITTED) public <T> T getFromRedisOrPutIntoMysql(String key, Supplier<T> mysqlSupplier, TypeReference<T> typeReference) { Opt.ofNullable(key).filter(StringUtils::isNotEmpty) .orElseThrow(() -> new MybatisPlusException("key不能为空")); String value = stringRedisTemplate.opsForValue().get(key); if (Objects.nonNull(value)) { return JSON.parseObject(value, typeReference); } synchronized (this) { return Opt.ofNullable(mysqlSupplier).map(Supplier::get) .peek(v -> stringRedisTemplate.opsForValue() .set(key, JSON.toJSONString(v), SECURE_RANDOM.nextInt(EXPIRE_SECONDS), TimeUnit.SECONDS)) .orElseGet(() -> { stringRedisTemplate.opsForValue() .set(key, "{}", SECURE_RANDOM.nextInt(EXPIRE_SECONDS), TimeUnit.SECONDS); return null; }); } }
}
|
使用方式
1 2 3 4 5 6 7 8 9 10 11 12
| @Resource private RedisManager redisManager;
@Test public void managerTest() { List<String> userIds = redisManager.getFromRedisOrPutIntoMysql("userIds", () -> { return Arrays.asList("1", "2", "3"); }, new TypeReference<List<String>>() { }); System.out.println(userIds); }
|
目前自己开发中用着感觉还不错的,大伙可以拿去自定义