Redis缓存工具封装实现(redis作为缓存在项目中怎么使用命令)新鲜出炉

随心笔谈9个月前更新 admin
175 00
🌐 经济型:买域名、轻量云服务器、用途:游戏 网站等 《腾讯云》特点:特价机便宜 适合初学者用 点我优惠购买
🚀 拓展型:买域名、轻量云服务器、用途:游戏 网站等 《阿里云》特点:中档服务器便宜 域名备案事多 点我优惠购买
🛡️ 稳定型:买域名、轻量云服务器、用途:游戏 网站等 《西部数码》 特点:比上两家略贵但是稳定性超好事也少 点我优惠购买

文章摘要

这篇文章介绍了名为`CacheClient`的Java类,该类使用Redis实现数据缓存和过期管理。文章详细描述了类的构造方法、几个主要方法(如`set`、`setWithLogicExpire`、`queryWithPassThrough`和`queryWithLogicalExpire`)以及Redis相关的操作。核心内容包括: 1. **类结构**:`CacheClient`通过`RedisTemplate`存储和操作数据,支持设置、获取、过期管理和锁机制。2. **缓存操作**:包括设置值、设置逻辑过期时间、查询数据,并在查询时判断数据是否过期,过期则重建缓存。3. **查询方法**:`queryWithPassThrough`直接获取数据,`queryWithLogicalExpire`在命中数据后检查过期状态,过期则触发重建。4. **锁管理**:通过尝试获取锁和释放锁来避免竞争访问,确保数据一致性。5. **缓存重建**:使用线程池在数据过期时自动重建缓存,提高处理效率。 文章重点突出了Redis缓存、过期管理、锁机制、线程池和数据查询方法,展示了`CacheClient`如何高效管理缓存数据。

@Component
@Slf4j
public class CacheClient {

? ? private final StringRedisTemplate stringRedisTemplate;

? ? public CacheClient(StringRedisTemplate stringRedisTemplate) {
? ? ? ? this.stringRedisTemplate=stringRedisTemplate;
? ? }

? ? public void set(String key, Object value, Long time, TimeUnit unit) {
? ? ? ? stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), time, unit);
? ? }

? ? public void setWithLogicExpire(String key, Object value, Long time, TimeUnit unit) {
? ? ? ? RedisData redisData=new RedisData();
? ? ? ? redisData.setData(value);
? ? ? ? redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));
? ? ? ? stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(redisData));
? ? }

? ? public <R, ID> R queryWithPassThrough(String keyPrefix, ID id, Class<R> type,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Long time, TimeUnit unit, Function<ID, R> dbFallback) {
? ? ? ? String key=keyPrefix + id;
? ? ? ? //1.从redis中查询商铺缓存
? ? ? ? String json=stringRedisTemplate.opsForValue().get(key);
? ? ? ? //2.判断是否存在
? ? ? ? if (StrUtil.isNotBlank(json)) {
? ? ? ? ? ? //2.1.存在
? ? ? ? ? ? return JSONUtil.toBean(json, type);
? ? ? ? }
? ? ? ? //2.2.不存在
? ? ? ? //判断是否为空值
? ? ? ? if (json !=null) {
? ? ? ? ? ? //不为null,则必为空
? ? ? ? ? ? return null;
? ? ? ? }
? ? ? ? //3.查询数据库
? ? ? ? R r=dbFallback.apply(id);
? ? ? ? if (r==null) {
? ? ? ? ? ? //3.1.不存在,缓存空值
? ? ? ? ? ? stringRedisTemplate.opsForValue().set(key, “”, CACHE_NULL_TTL, TimeUnit.MINUTES);
? ? ? ? } else {
? ? ? ? ? ? //3.2.存在,缓存数据
? ? ? ? ? ? this.set(key, r, time, unit);
? ? ? ? }
? ? ? ? return r;
? ? }

? ? public <R, ID> R queryWithLogicalExpire(String prefix, ID id, String lockPre, Class<R> type,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Long time, TimeUnit unit, Function<ID, R> dbFallback) {
? ? ? ? //1.从redis查询商铺缓存
? ? ? ? String key=prefix + id;
? ? ? ? String json=stringRedisTemplate.opsForValue().get(key);
? ? ? ? //2.判断是否存在
? ? ? ? if (StrUtil.isBlank(json)) {
? ? ? ? ? ? //未命中,直接返回空
? ? ? ? ? ? return null;
? ? ? ? }
? ? ? ? //3.命中,判断是否过期
? ? ? ? RedisData redisData=JSONUtil.toBean(json, RedisData.class);
? ? ? ? R r=JSONUtil.toBean((JSONObject) redisData.getData(), type);
? ? ? ? if (redisData.getExpireTime().isAfter(LocalDateTime.now())) {
? ? ? ? ? ? //3.1未过期,直接返回店铺信息
? ? ? ? ? ? return r;
? ? ? ? }
? ? ? ? //3.2.已过期,缓存重建
? ? ? ? //3.3.获取锁
? ? ? ? String lockKey=lockPre + id;
? ? ? ? boolean flag=tryLock(lockKey);
? ? ? ? if (flag) {
? ? ? ? ? ? //3.4.获取成功
? ? ? ? ? ? //4再次检查redis缓存是否过期,做double check
? ? ? ? ? ? json=stringRedisTemplate.opsForValue().get(key);
? ? ? ? ? ? //4.1.判断是否存在
? ? ? ? ? ? if (StrUtil.isBlank(json)) {
? ? ? ? ? ? ? ? //未命中,直接返回空
? ? ? ? ? ? ? ? return null;
? ? ? ? ? ? }
? ? ? ? ? ? //4.2.命中,判断是否过期
? ? ? ? ? ? redisData=JSONUtil.toBean(json, RedisData.class);
? ? ? ? ? ? r=JSONUtil.toBean((JSONObject) redisData.getData(), type);
? ? ? ? ? ? if (redisData.getExpireTime().isAfter(LocalDateTime.now())) {
? ? ? ? ? ? ? ? //4.3.未过期,直接返回店铺信息
? ? ? ? ? ? ? ? return r;
? ? ? ? ? ? }
? ? ? ? ? ? //4.4过期,返回旧数据
? ? ? ? ? ? CACHE_REBUILD_EXECUTOR.submit(() -> {
? ? ? ? ? ? ? ? //5.重建缓存
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? R r1=dbFallback.apply(id);
? ? ? ? ? ? ? ? ? ? this.setWithLogicExpire(key, r1, time, unit);
? ? ? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? ? ? throw new RuntimeException(e);
? ? ? ? ? ? ? ? } finally {
? ? ? ? ? ? ? ? ? ? //释放锁
? ? ? ? ? ? ? ? ? ? unLock(lockKey);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? });
? ? ? ? }
? ? ? ? //7.获取失败,返回旧数据
? ? ? ? return r;
? ? }

? ? private static final ExecutorService CACHE_REBUILD_EXECUTOR=Executors.newFixedThreadPool(10);

? ? //获取锁
? ? private boolean tryLock(String key) {
? ? ? ? Boolean flag=stringRedisTemplate.opsForValue().setIfAbsent(key, “1”, LOCK_SHOP_TTL, TimeUnit.SECONDS);
? ? ? ? return BooleanUtil.isTrue(flag);
? ? }

? ? //释放锁
? ? private void unLock(String key) {
? ? ? ? stringRedisTemplate.delete(key);
? ? }
}

© 版权声明

相关文章