前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redis的manager层应用

redis的manager层应用

作者头像
阿超
发布2022-08-16 20:19:41
3220
发布2022-08-16 20:19:41
举报
文章被收录于专栏:快乐阿超

一身报国有万死,双鬓向人无再青。 —— 陆游

封装了一个操作redis的管理层,简单处理了缓存穿透、击穿、雪崩问题

Manager

代码语言:javascript
复制
package com.ruben.manager;

import com.alibaba.fastjson.TypeReference;

import java.util.function.Supplier;

/**
 * redis管理层
 *
 * @author <achao1441470436@gmail.com>
 * @since 2021/6/11 0011 21:55
 */
public interface RedisManager {

    /**
     * 从缓存中获取否则从mysql中查询
     *
     * @param key           缓存中的key
     * @param mysqlSupplier 查询mysql操作
     * @param typeReference 返回的类型
     * @param <T>           数据类型
     * @return 数据
     */
    <T> T getFromRedisOrPutIntoMysql(String key, Supplier<T> mysqlSupplier, TypeReference<T> typeReference);
}

实现类

代码语言:javascript
复制
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;

/**
 * redis管理层实现类
 *
 * @author <achao1441470436@gmail.com>
 * @since 2021/6/11 0011 21:55
 */
@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;


    /**
     * 从缓存中获取否则从mysql中查询
     *
     * @param key           缓存中的key
     * @param mysqlSupplier 查询mysql操作
     * @param typeReference 返回的类型
     * @param <T>           数据类型
     * @return 数据
     */
    @Override
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED, isolation = Isolation.READ_UNCOMMITTED)
    public <T> T getFromRedisOrPutIntoMysql(String key, Supplier<T> mysqlSupplier, TypeReference<T> typeReference) {
        // 判断传入key是否为空
        Opt.ofNullable(key).filter(StringUtils::isNotEmpty)
                .orElseThrow(() -> new MybatisPlusException("key不能为空"));
        // 如果redis中存在,直接返回
        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))
                    // 没值则放入空对象"{}"【缓存穿透】并返回null
                    .orElseGet(() -> {
                        stringRedisTemplate.opsForValue()
                                .set(key, "{}", SECURE_RANDOM.nextInt(EXPIRE_SECONDS), TimeUnit.SECONDS);
                        return null;
                    });
        }
    }

}

使用方式

代码语言:javascript
复制
@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);
}

目前自己开发中用着感觉还不错的,大伙​可以拿去自定义

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-06-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis®
腾讯云数据库 Redis®(TencentDB for Redis®)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档