分布式锁Redisson实战(二)自定义注解

Redisson中红锁(RedLock)的实现 当在单点redis中实现redis锁时,一旦redis服务器宕机,则无法进行锁操作。因此会考虑将redis配置为主从结 构,但在主从结构中,数据复制是异步实现的。假设在主从结构中,master会异步将数据复制到slave中,一旦某 个线程持有了锁,在还没有将数据复制到slave时,master宕机。则slave会被提升为master,但被提升为slave的 master中并没有之前线程的锁信息,那么其他线程则又可以重新加锁。 阅读详情

package com.*.data.busisystem;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lock {
    /** 模块 */
    String operateModelNM() default "";
 
    /**描述*/
    String operateDescribe() default"";
}

package com.*.data.busisystem;


import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.Config;
import org.redisson.RedissonClient;
import org.redisson.SingleServerConfig;
import org.redisson.core.RBucket;
import org.redisson.core.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Controller;
 
@Aspect
@EnableAspectJAutoProxy
@Controller("lockAspect")
public class LockAspect {
 
    private static final Logger log = LoggerFactory.getLogger(LockAspect.class);
    @Autowired
    private RedisUtils redisUtils;
    
    private RLock lock;
    // 配置织入点
    @Pointcut("@annotation(com.*.data.busisystem.Lock)")
    public void logPointCut() {
        
    }
 
    /**
     * 前置通知 用于拦截操作,在方法返回后执行
     * @param joinPoint 切点
     */
    @Before(value = "logPointCut()")
    public void doBefore(JoinPoint joinPoint) {
        Config config = new Config();
        SingleServerConfig singleSerververConfig = config.useSingleServer();
        singleSerververConfig.setAddress("10.114.10.37:9101");
        singleSerververConfig.setPassword("admin");
        //redisson客户端
//        RedissonClient redissonClient = RedisUtils.getInstance().getRedisson(config);
        RedissonClient redissonClient = redisUtils.getRedisson();
//        RBucket<Object> rBucket = redisUtils.getRBucket(redissonClient, "key");
//        lock = redissonClient.getLock("lock");

        RBucket<Object> rBucket = redisUtils.getRBucket("key");
        lock = redisUtils.getRLock("lock");
        try {
            System.out.println("加锁前");
            lock.tryLock(0, 100, TimeUnit.SECONDS);
            System.out.println("加锁后");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 
    /**
     * 拦截异常操作,有异常时执行
     *
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        this.release();
        
    }
    @AfterReturning(value = "logPointCut()")
    public void doAfter(JoinPoint joinPoint) {
        System.out.println("释放锁前");
        this.release();
        System.out.println("释放锁后");
    }
 
    private void release() {
         lock.unlock();
        
    }

    /**
     * 是否存在注解,如果存在就获取
     */
    private static Lock getAnnotationLog(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(Lock.class);
         }
            return null;
     }
 
    
    /**
     *
     * @title getIpAddress
     *        <ul>
     * @description
     *              <li>获取IP地址
     *              <li><strong>注意:</strong>IP地址经过多次反向代理后会有多个IP值,
     *              <li>其中第一个IP才是真实IP,所以不能通过request.getRemoteAddr()获取IP地址,
     *              <li>如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,
     *              <li>X-Forwarded-For中第一个非unknown的有效IP才是用户真实IP地址。
     *              </ul>
     * @param request
     * @return String
     *
     * @version : V1.0.0
     */
    public static String getIpAddress(HttpServletRequest request)
    {
        String ip = null;
        try
        {
            // 获取用户真是的地址
            String Xip = request.getHeader("X-Real-IP");
            // 获取多次代理后的IP字符串值
            String XFor = request.getHeader("X-Forwarded-For");
            if (StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor))
            {
                // 多次反向代理后会有多个IP值,第一个用户真实的IP地址
                int index = XFor.indexOf(",");
                if (index >= 0)
                {
                    return XFor.substring(0, index);
                } else
                {
                    return XFor;
                }
            }
            ip = Xip;
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip))
            {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
            {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip))
            {
                ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip))
            {
                ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip))
            {
                ip = request.getRemoteAddr();
            }
            if(ip.equalsIgnoreCase("0:0:0:0:0:0:0:1")){
                ip = "127.0.0.1";
            }
        } catch (Exception e)
        {
            log.error(e.getMessage(), e);
        }
        return ip;
    }
    
}

 

Redisson之——使用Redisson通过自定义注解实现分布式锁,使用Spring AOP简化分布式锁 这份面试题几乎包含了他在一年内遇到的所有面试题以及答案,甚至包括面试中的细节对话以及语录,可谓是细节到极致,甚至简历优化和怎么投简历更容易得到面试机会也包括在内!也包括教你怎么去获得一些大厂,比如阿里,腾讯的内推名额!某位名人说过成功是靠99%的汗水和1%的机遇得到的,而你想获得那1%的机遇你首先就得付出99%的汗水!你只有朝着你的目标一步一步坚持不懈的走下去你才能有机会获得成功!成功只会留给那些有准备的人!《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》 阅读详情

相关推荐

Springboot+分布式锁Redisson注解封装

redisson注解封装

Think_and_work的博客 902

Redisson--红锁(Redlock)--使用/原理

本文介绍为什么要使用Redis的红锁(Redlock)、什么是Redis的红锁以及Redis红锁的原理。 本文用Redisson来介绍Redis红锁的用法。 Redisson 高版本会根据redisClient的模式来决定getLock返回的锁类型,如果集群模式,满足红锁的条件,则会直接返回红锁。

IT利刃出鞘的博客 7万+

MATLAB实战:5步搞定GNSS单点定位解算(附完整代码)

本文提供了一份基于MATLAB的GNSS单点定位实战指南。通过5个核心步骤,详细讲解了如何从卫星坐标和伪距观测值出发,利用最小二乘迭代算法,构建并实现一个完整的单点定位解算器。文章附有完整代码,并涵盖精度评估与结果分析,适合GNSS初学者和MATLAB用户快速上手实践。

a2b3c4d5e的博客 249

Redisson——联合锁和红锁

联合锁和红锁放在一起来分析,是因为这两种锁实现在Redisson中,关联密切。红锁是官方提出的一个锁方案,大概如下:假设redis集群有5个节点,一个客户端申请锁时,会向所有的节点申请锁,只有大于一半的节点数量返回成功,且耗费的总时间小于锁有效时间,才会判定为拿锁成功,否则会被认定为失败,需要将已经成功的节点锁释放掉。

m0_64363449的博客 1655

中微8S6990外设开发实战:从GPIO配置到低功耗休眠的完整指南

本文提供了中微8S6990增强型8051单片机从GPIO配置到低功耗休眠的完整实战指南。详细讲解了开发环境搭建、GPIO灵活配置、定时器中断、ADC采样优化、PWM电机控制等核心外设的编程要点与避坑技巧,并重点阐述了实现超低功耗休眠的系统性外设管理策略,帮助开发者快速上手并优化产品续航。

weixin_29162439的博客 533

【SABRE 3D, SABRE 3DxT,LAM设备】2025年9月12日-生产期间维护用的双重隔离

生产期间维护用的双重隔离。该程序用于准备将一个或多个双工位设置为维护状态,同时SABRE 3D/3DxT/3D Scimitar保持生产运行。其目的是在不中断生产的情况下将双工位与运行中的设备隔离。

weixin_46735260的博客 574

Redisson红锁

一、红锁概述 Redisson红锁(RedissonRedLock)实现了Redis官网RedLock的加锁算法。与联锁类似,也可以用来将多个RLock对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例。 二、实践 配置文件相关内容可以参考我的上一篇文章Redisson联锁 具体使用方式如下: RLock lock1 = redissonClient1.getLock("lock1"); RLock lock2 = redissonClient2.getLock("lock2")

sinat_34241861的博客 2437

手把手教你用VMware虚拟机搭建PCAN开发环境:从Ubuntu安装到CAN通讯实战

本文详细指导如何在VMware虚拟机中搭建PCAN开发环境,涵盖从Ubuntu系统安装、VMware精细配置、PCAN-USB设备直通,到Linux驱动编译、can-utils工具集使用及完整CAN通讯测试的全过程。通过实战步骤与故障排查技巧,帮助开发者快速构建稳定高效的CAN总线开发与测试沙盒,特别适合车载诊断与嵌入式通讯应用。

weixin_29216353的博客 221

分布式锁-Redis红锁解决方案

红锁本质上就是使用多个Redis做锁。例如有5个Redis,一次锁的获取,会对每个请求都获取一遍,如果获取锁成功的数量超过一半(2.5),则获取锁成功,反之失败;释放锁也需要对每个Redis释放基于Redis的Redisson红锁RedissonRedLock对象实现了Redlock介绍的加锁算法。该对象也可以用来将多个RLock对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例。// 同时加锁:lock1 lock2 lock3。

tian830937的专栏 3415

WPF数据可视化:LiveCharts自定义X轴与Y轴的5个实战技巧(附完整代码)

本文详细介绍了在WPF应用中使用LiveCharts进行数据可视化时,自定义X轴与Y轴的5个核心实战技巧。内容涵盖精确控制刻度步距、深度定制视觉样式、实现多轴布局对比、优化显示空间以及构建响应式动态轴,并提供了完整的C#和XAML代码示例,帮助开发者创建专业且用户体验出色的图表。

moss5的博客 690

基于SiamFC的红外目标跟踪

初始化阶段:在第一帧中,通过用户标注获得目标框,从目标区域中提取一个固定大小的模板(称为 exemplar)。搜索阶段:在后续帧中,在以当前目标中心为中心的较大区域(称为 instance)内进行搜索,将模板与搜索区域通过卷积操作得到响应图。位置更新:在响应图中找到峰值位置,并转换到原图坐标,用以更新目标中心。部分实现中还会考虑多尺度搜索和目标尺寸更新。import cv2# 定义 SiamFC 简易网络(示例)# 特征提取部分,注意红外图像通常为单通道,使用较少的卷积核数提高实时性。

weixin_43745234的博客 774

Spring Boot 集成 Redisson分布式锁(注解版)

在 Spring Boot 应用程序中使用 Redisson 可以方便地实现分布式应用程序的某些方面,例如分布式锁、分布式集合、分布式事件发布和订阅等。本篇是一个使用 Redisson 实现分布式锁的详细示例,在这个示例中,我们定义了DistributedLock注解,它可以标注在方法上,配合DistributedLockAspect切面以及IDistributedLock分布式锁封装的接口,来实现redisson 分布式锁的 API 调用。

Ascend1977的博客 1万+

【DRAM存储器五十六】LPDDR5介绍--WCK2CK Leveling和Read gate training

简述LPDDR5 WCK2CK leveling和read gate traning基本原理与操作步骤

highman110的博客 8786

【4】【实战分布式锁三】SpringBoot注解整合Redisson分布式锁

Redisson是架设在Redis基础上的一个Java驻内存数据网格(In-Memory Data Grid)。充分的利用了Redis键值数据库提供的一系列优势,基于Java实用工具包中常用接口,为使用者提供了一系列具有分布式特性的常用工具类。...............

莫安逸无风雪 2万+

IMEI引起的无法驻网问题

问题不复杂,场景很简单,如上图,UE在进行LTE attach过程时,在送完NAS security mode complete后,就立刻收到了网络attach reject 带cause 6 Illegal ME,根据协议描述这个cause 代表ME不被网络可接受,例如ME在禁止名单或者黑名单中就会有这种cause。然而前方在报这个问题的时候,也是知道SIM卡和手机IMEI在运营商那边没能成功绑定,然后才报的问题,要查看手机是不是有问题...... 告诉前方原因后,还认为是手机问题,告知要继续查。

asd199086的博客 1425

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【Redisson】基于自定义注解的Redisson分布式锁实现

在项目中,经常需要使用Redisson分布式锁来保证并发操作的安全性。在未引入基于注解的分布式锁之前,我们需要手动编写获取锁、判断锁、释放锁的逻辑,导致代码重复且冗长。为了简化这一过程,我们引入了基于注解的分布式锁,通过一个注解就可以实现获取锁、判断锁、处理完成后释放锁的逻辑。这样可以大大简化代码,提高开发效率。

Java全栈开发者 2173

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

用Redisson自定义注解解锁分布式锁的神秘力量~

标准锁(也称为非公平锁)是最常见的锁类型,它不保证线程获得锁的顺序。任何等待的线程都可以在锁释放时争夺锁,可能会发生"锁抢占"现象,导致某些线程长时间得不到锁。特性:不保证线程获取锁的顺序,先来先得、适用于大多数需要并发访问资源的场景。使用场景:适用于对性能要求较高且不太关注公平性的场景。Redisson 中的实现公平锁是一种确保锁的请求顺序与请求的顺序相同的锁。也就是说,先请求锁的线程先获得锁,避免了线程饥饿的问题。

2401_89221867的博客 879

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

SpringBoot通过自定义注解整合Redisson实现分布式锁(单机+集群模式)

SpringBoot通过自定义注解整合Redisson实现分布式锁(单机+集群模式)

一恍过去 1万+

自定义注解 + AOP + Redisson:优雅实现分布式锁(增强版)

分布式锁是一种在分布式系统中用于控制多个进程或线程对共享资源访问的机制。互斥性:同一时刻只有一个客户端可以持有锁。可重入性:同一个客户端可以多次获取同一把锁。高可用性:锁服务需要具备高可用性,避免单点故障。自动释放:锁需要支持超时自动释放,避免死锁。定义一个注解// 锁的key,支持SpEL表达式 long waitTime() default 30;// 获取锁的最大等待时间(秒) long leaseTime() default 10;// 锁的持有时间(秒) }

双非二本自学到互联网公司的成长经历,有故事,有干货。 1522

【SpringBoot实战系列】从AOP+自定义注解到redission分布式锁-接口防重提交场景设计实战

自定义注解 分布式锁 aop

chandfy的博客 1758

干货,springboot自定义注解实现分布式锁详解

背景 在互联网的很多场景下,会产生资源竞争,如果是单机环境,简单加个锁就能解决问题;但是在集群环境下(分布式环境),多个客户端在一个很短的时间内竞争同一服务端资源(如抢购场景),或者同一客户端重复提交请求,如果请求不具备幂等性,就需要用到分布式锁的解决方案。 背景知识 关于分布式锁,可以看看我之前的文章《基于Spring boot 2.1 使用redisson实现分布式锁》,当时只是利用...

勇往直前的专栏 4074

Redisson分布式锁使用详解

通常我们都会将redisson实例注入到方法类里面,然后调用加锁方法进行加锁,如果其他业务方法也需要加锁执行,将会产生很多重复代码,由此采用AOP切面的方式,只需要通过注解的方式就能将方法进行加锁处理。自定义注解@InheritedString errorDesc() default "系统正常处理,请稍后提交";切面类实现@Aspect@Component@Autowiredtry {if (!lock) {

2301_76166241的博客 1799

注解方式优雅的实现Redisson分布式锁

通常我们都会将redisson实例注入到方法类里面,然后调用加锁方法进行加锁,如果其他业务方法也需要加锁执行,将会产生很多重复代码,由此采用AOP切面的方式,只需要通过注解的方式就能将方法进行加锁处理。/*** @date 2023年11月27日String errorDesc() default "系统正常处理,请稍后提交";/*** @date 2023年11月27日String errorDesc() default "系统正常处理,请稍后提交";/**

zhiyikeji的博客 1103

天机学堂7--Redisson自定义注解AOP以及SPEL表达式实现分布式锁

通知类:里面的切点表达式,public是方法返回类型,路径…*是service及其子包下的类 后面的.*是任意方法 (…)指任意参数(@annotation(路径.实现类中方法的注解)@Around("@annotation(xxx类)")以上图为例,只要方法加了@printTime注解,方法就是切点,再走这个方法之前就会走环绕通知@Around()around()方法。

juli_eyre的博客 1445
上一篇: 分布式锁Redisson实战(一)RedisUtils工具类和maven坐标
下一篇: 分布式锁Redisson实战(三)测试controller
qq_34412985
博客等级 码龄11年 143粉丝 983原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值