redisson+aop实现分布式锁

这篇具有很好参考价值的文章主要介绍了redisson+aop实现分布式锁。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基于注解实现,一个注解搞定缓存

Aop:面向切面编程,在不改变核心代码的基础上实现扩展,有以下应用场景

①事务

②日志

③controlleradvice+expetcationhandle实现全局异常

④redissson+aop实现分布式锁

⑤认证授权

Aop的实现存在与bean的后置处理器beanpostprocessAfterinitlazing

一,实现步骤

1.定义注解

注解的定义仿照@translation进行定义



@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface GmallCache {
    //注解里面的自定义参数
    String prefix() default "cache";
    String suffix() default "info";
}

2.创建切面

参照官网

https://docs.spring.io/spring-framework/docs/5.3.9-SNAPSHOT/reference/html/core.html#aop文章来源地址https://www.toymoban.com/news/detail-805593.html


@Aspect     //定义一个切面
@Component  //交给ioc管理
public class GmallAspect {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;


    /**
     * 使用注解+aop实现缓存实现思路
     * ①首先的定义一个注解,仿照@transactional注解去实现,他就是在aop的基础上实现的
     * ②定义一个切面,交由ioc容器来管理
     * ③去官网找到环绕通知的实例在此基础上进行修改
     * ④around注解里面扫描所有加了定义注解的内容
     * ⑤方法体里面首先获取添加了注解的方法,然后获取方法上的注解以及里面的参数
     * ⑥一切准备就绪,准备redis里面的key,先从redis里面查询,根据json数据,判断是否为空,如果为空直接返回空,如果不为空,则获取运行时类型,根据反射拿到对象
     *⑦redis里面有,直接返回
     * ⑧redis里面没有,定义lockKey,上锁
     * ⑨判断是否拿到锁,拿不到则等待一会儿,并自旋
     * ⑩拿到锁,则从数据库查询
     *          查询到:存往redis,返回,由于不确定对象的类型,此处存往reids使用json格式
     *          查询不到:预防缓存穿透①存空串(不建议)②使用反射创建空对象返回
     *  十一:释放锁
     */

    //定义一个环绕通知并且扫描,简单的说就是对加了这个注解的所有方法增强
    @Around("@annotation(com.atguigu.gmall.common.cache.GmallCache)")
    public Object gmallCacheImpl(ProceedingJoinPoint joinPoint) throws Throwable {
        //创建返回对象
        Object object = new Object();
        //获取加了注解的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        //获取注解
        GmallCache annotation = method.getAnnotation(GmallCache.class);
        //获取注解参数
        String prefix = annotation.prefix();
        String suffix = annotation.suffix();
        //准备key
        String key = prefix + Arrays.toString(joinPoint.getArgs()) + suffix;
        //从缓存里面查询
        object = cacheNull(key, signature);
        //判断缓存是否存在
        if (ObjectUtils.isEmpty(object)) {
            //不存在,从数据库查询
            //上锁
            String lockKey = prefix + Arrays.toString(joinPoint.getArgs());
            //获取锁
            RLock lock = redissonClient.getLock(lockKey);
            boolean res = lock.tryLock(20, 10, TimeUnit.SECONDS);//此处数字要定义为常量
            try {
                if (res) {
                    //获取到了锁
                    //从数据库查询
                    object = joinPoint.proceed();
                    if (ObjectUtils.isEmpty(object)) {
                        //使用拿到返回值的运行时类型,使用反射创建对象
                        Object instance = signature.getReturnType().newInstance();
                        //数据库查询不到,预防缓存穿透
                       // Object obj = new Object();
                        //存储到数据库
                        redisTemplate.opsForValue().setIfAbsent(key, JSON.toJSONString(instance), 15, TimeUnit.SECONDS);
                        return instance;//返回skuinfo
                    } else {
                        //查询到了
                        //存储到数据库
                        redisTemplate.opsForValue().set(key, JSON.toJSONString(object));
                        return object;
                    }
                } else {
                    //没有获取到等待,自旋
                    Thread.sleep(300);
                    return gmallCacheImpl(joinPoint);
                }
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            } finally {
                //解锁
                lock.unlock();
            }
        } else {
            //存在
            return object;
        }
        //保底从数据库查询
        return joinPoint.proceed();
    }

    /**
     * 从缓存查询数据
     *
     * @param key
     * @param signature
     * @return
     */
    private Object cacheNull(String key, MethodSignature signature) {
        String str = (String) redisTemplate.opsForValue().get(key);
        if (!StringUtils.isEmpty(str)) {
            //获取返回类型
            Class returnType = signature.getReturnType();
            //转换
            Object object = JSON.parseObject(str, returnType);
            return object;
        }

        return null;
    }


}


到了这里,关于redisson+aop实现分布式锁的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微服务系列文章之 Redisson实现分布式锁

    当我们在设计分布式锁的时候,我们应该考虑分布式锁至少要满足的一些条件,同时考虑如何高效的设计分布式锁,这里我认为以下几点是必须要考虑的。 1、互斥 在分布式高并发的条件下,我们最需要保证,同一时刻只能有一个线程获得锁,这是最基本的一点。 2、防止死

    2024年02月15日
    浏览(98)
  • Spring Boot 集成 Redisson 实现分布式锁

            Redisson 是一种基于 Redis 的 Java 驻留集群的分布式对象和服务库,可以为我们提供丰富的分布式锁和线程安全集合的实现。在 Spring Boot 应用程序中使用 Redisson 可以方便地实现分布式应用程序的某些方面,例如分布式锁、分布式集合、分布式事件发布和订阅等。本篇

    2024年02月08日
    浏览(38)
  • Redis分布式锁及Redisson的实现原理

    Redis分布式锁 在讨论分布式锁之前我们回顾一下一些单机锁,比如synchronized、Lock 等 锁的基本特性: 1.互斥性:同一时刻只能有一个节点访问共享资源,比如一个代码块,或者同一个订单同一时刻只能有一个线程去支付等。 2.可重入性: 允许一个已经获得锁的线程,在没有释

    2024年02月06日
    浏览(43)
  • 源码篇--Redisson 分布式锁lock的实现

    我们知道Redis 缓存可以使用setNx来作为分布式锁,但是我们直接使用setNx 需要考虑锁过期的问题;此时我们可以使用Redisson 的lock 来实现分布式锁,那么lock 内部帮我们做了哪些工作呢。 RedisConfig.java lock.lock() 阻塞获取 redis 锁,获取到锁之后继续向下执行业务逻辑; lockInterr

    2024年01月25日
    浏览(46)
  • 在Java项目中使用redisson实现分布式锁

    在Java项目中使用Redission自定义注解实现分布式锁: 添加Redission依赖项:在项目的pom.xml中添加Redission依赖项: 创建自定义注解:创建一个自定义注解来标记需要使用分布式锁的方法。例如,创建一个名为 @DistributedLock 的注解: 创建注解切面:创建一个切面类,通过AOP将注解

    2024年02月16日
    浏览(37)
  • 微服务系列文章之 Redisson实现分布式锁(2)

    1、概念 很明显RLock是继承Lock锁,所以他有Lock锁的所有特性,比如lock、unlock、trylock等特性,同时它还有很多新特性:强制锁释放,带有效期的锁,。 2、RLock锁API 这里针对上面做个整理,这里列举几个常用的接口说明 RLock相关接口,主要是新添加了  leaseTime  属性字段,主要是

    2024年02月16日
    浏览(32)
  • 微服务系列文章之 Redisson实现分布式锁(3)

    1、技术架构 项目总体技术选型 2、加锁方式 该项目支持  自定义注解加锁  和  常规加锁  两种模式 自定义注解加锁 常规加锁 3、Redis部署方式 该项目支持四种Redis部署方式 该项目已经实现支持上面四种模式,你要采用哪种只需要修改配置文件 application.properties ,项目代码

    2024年02月16日
    浏览(38)
  • 【Redisson】分布式锁源码分析如何实现多个应用实例互斥

    lockName就是保存到Redis里面的key 直接进行构建方法里面的 super(commandExecutor, name); org.redisson.connection.ServiceManager : private final String id = UUID.randomUUID().toString(); 这个 id 就是 UUID : this.id = getServiceManager().getId(); 这个entryName通过UUID可以区分是哪个应用实例 entryName+threadId可以区分哪个应

    2024年02月11日
    浏览(40)
  • redis实战-redis实现分布式锁&redisson快速入门

    前言 集群环境下的并发问题  分布式锁 定义 需要满足的条件 常见的分布式锁 redis实现分布式锁 核心思路 代码实现 误删情况 逻辑说明 解决方案 代码实现 更为极端的误删情况 Lua脚本解决原子性问题 分布式锁-redission redisson的概念 快速入门 总结 在前面我们已经实现了单机

    2024年02月09日
    浏览(47)
  • spring boot 实现Redisson分布式锁及其读写锁

    分布式锁,就是控制分布式系统中不同进程共同访问同一共享资源的一种锁的实现。 1、引入依赖 2、配置文件 3、配置类 4、测试代码 5、理解 一、时间设置 默认 lock() 小结 lock.lock (); (1)默认指定锁时间为30s(看门狗时间) (2)锁的自动续期:若是业务超长,运行期间自

    2024年02月12日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包