redis分布式秒杀锁

news2025/1/12 12:26:42

在这里插入图片描述

-- 获取锁标识,是否与当前线程一致?
if(redis.call('get', KEYS[1]) == ARGV[1]) then
    -- 一致,删除
    return redis.call('del', KEYS[1])
end
-- 不一致,直接返回
return 0

在这里插入图片描述

package com.platform.lock;

public interface ILock {

    /**
     * 获取锁
     * @param timeoutSec
     * @return
     */
    public boolean tryLock(long timeoutSec);

    /**
     * 锁标识、释放锁
     */
    public void unlock();
}

在这里插入图片描述

package com.platform.lock;

import cn.hutool.core.lang.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * redis的分布式锁
 * 实现ILock接口
 */
public class SimpleRedisLock implements ILock {

    // 不同的业务有不同的锁名称
    private String name;

    private StringRedisTemplate stringRedisTemplate;
    private static final String KEY_PREFIX = "tryLock:";
    private static final String ID_PREFIX = UUID.randomUUID().toString(true) + "-";
    // DefaultRedisScript,
    private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;

    public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {
        this.name = name;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    // 初始化 UNLOCK_SCRIPT,用静态代码块的方式,一加载SimpleRedisLock有会加载unlock.lua
    // 避免每次调unLock() 才去加载,提升性能!!!
    static {
        UNLOCK_SCRIPT = new DefaultRedisScript<>();
        // setLocation() 设置脚本位置
        UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
        // 返回值类型
        UNLOCK_SCRIPT.setResultType(Long.class);
    }

    /**
     * 获取锁
     */
    @Override
    public boolean tryLock(long timeoutSec) {
        // 获取线程标示
        String threadId = ID_PREFIX + Thread.currentThread().getId();
        // 获取锁
        // set lock thread1 nx ex 10
        // nx : setIfAbsent(如果不存在) , ex : timeoutSec(秒)
        Boolean success = stringRedisTemplate.opsForValue()
                .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        // 自动拆箱(Boolean -> boolean)!!!可能有风险
        return Boolean.TRUE.equals(success);
    }

    /**
     * 解决判断(锁标识、释放锁)这两个动作,之间产生阻塞!!!
     * JVM的 FULL GC
     * 要让这两个动作具有原子性
     */
    @Override
    public void unlock() {
        // 调用lua脚本
        stringRedisTemplate.execute(
                UNLOCK_SCRIPT,
                Collections.singletonList(KEY_PREFIX + name),
                ID_PREFIX + Thread.currentThread().getId());
    }
}

在这里插入图片描述

    @PostMapping("/cancelPublicBenefit")
    @CheckRepeatCommit
    public RestResponse cancelPublicBenefit(@LoginUser MallUserEntity loginUser, @RequestBody MallPublicBenefitEntity publicBenefitEntity) {

        String key = PUBLIC_BENEFIT_TEAM_LOCK_FLAG + publicBenefitEntity.getId();
        RestResponse restResponse = null;

        SimpleRedisLock simpleRedisLock = new SimpleRedisLock(key,stringRedisTemplate);
        try {
            if (simpleRedisLock.tryLock(15)) {
                // 成功获取锁,执行业务逻辑
                restResponse = mallPublicBenefitService.cancelPublicBenefit(loginUser, publicBenefitEntity);
            } else {
                // 获取锁失败,处理失败逻辑
                throw new BusinessException("服务器繁忙!");
            }
        } finally {
            simpleRedisLock.unlock();
        }

        return restResponse;
    }

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1067667.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2.5 数字传输系统

笔记&#xff1a; 针对这一节的内容&#xff0c;我为您提供一个笔记的整理方法。将内容按重要性、逻辑关系进行组织&#xff0c;再进行简化。 ## 2.5 数字传输系统 ### 背景介绍&#xff1a; 1. **早期电话网**&#xff1a;市话局到用户采用双绞线电缆&#xff0c;长途干线采…

Ubuntu 20.04使用源码安装nginx 1.14.0

nginx安装及使用&#xff08;详细版&#xff09;是一篇参考博文。 http://nginx.org/download/可以选择下载源码的版本。 sudo wget http://nginx.org/download/nginx-1.14.0.tar.gz下载源代码。 sudo tar xzf nginx-1.14.0.tar.gz进行解压。 cd nginx-1.14.0进入到源代码…

ping使用

使用shell ping一个网段 #!/bin/shfor ib in $(seq 1 254); doip"192.168.1.$ib"(if ping -c3 "$ip" >> 1.txt; thenecho "$ip is alive"fi) &done wait在每次循环的最后&#xff0c;使用 & 将子 shell 放入后台执行&#xff0c…

怒刷LeetCode的第25天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;闭合为环 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;动态规划 方法二&#xff1a;组合数学 方法三&#xff1a;递归 方法四&#xff1a;数学公式 第三题 题目来源 题目内容 解决方法 …

ctfshow-web3(伪协议php://input的利用)

打开题目链接&#xff0c;存在文件包含函数 include 存在文件包含时直接使用PHP伪协议 先介绍一下一个常用的php伪协议&#xff1a; php://input&#xff08;用于执行PHP代码&#xff09; 这是一个只读信息流&#xff0c;当请求方式是post的&#xff0c;并且enctype不等于…

Flink---10、处理函数(基本处理函数、按键分区处理函数、窗口处理函数、应用案例TopN、侧输出流)

星光下的赶路人star的个人主页 我的敌手就是我自己&#xff0c;我要他美好到能使我满意的程度 文章目录 1、处理函数1.1 基本处理函数&#xff08;ProcessFunction&#xff09;1.1.1 处理函数的功能和使用1.1.2 ProcessFunction解析1.1.3 处理函数的分类 1.2 按键分区处理函数&…

Charles:移动端抓包 / windows客户端 iOS手机

一、背景描述 1.1、本文需求&#xff1a;移动端进行抓包调试 1.2、理解Charles可以做什么 Charles是一款跨平台的网络代理软件&#xff0c;可以用于捕获和分析网络流量&#xff0c;对HTTP、HTTPS、HTTP/2等协议进行调试和监控。使用Charles可以帮助开发人员进行Web开发、调试…

【MySQL】Linux 中 MySQL 环境的安装与卸载

文章目录 Linux 中 MySQL 环境的卸载Linux 中 MySQL 环境的安装 Linux 中 MySQL 环境的卸载 在安装 MySQL 前&#xff0c;我们需要先将系统中以前的环境给卸载掉。 1、查看以前系统中安装的 MySQL rpm -qa | grep mysql2、卸载这些 MySQL rpm -qa | grep mysql | args yum …

【Unity】RenderFeature笔记

【Unity】RenderFeature笔记 RenderFeature是在urp中添加的额外渲染pass&#xff0c;并可以将这个pass插入到渲染列队中的任意位置。内置渲染管线中Graphics 的功能需要在RenderFeature里实现,常见的如DrawMesh和Blit ​ 可以实现的效果包括但不限于 后处理&#xff0c;可以编写…

ruoyi-cloud新增模块示例(亲自操作,可行)

1.在ruoyi-modules模块下新建模块&#xff08;ruoyi-search&#xff09; 2.重命名模块的名称 3.在ruoyi-modules添加新模块依赖 4.复制ruoyi-system模块的pom文件&#xff0c;并进行修改 <?xml version"1.0" encoding"UTF-8"?> <project xmlns…

JetPack系列:001-JetPack概要介绍

文章目录 1. 概念介绍2. 主要内容2.1 框架库2.2 UI界面库 3. 核心思想4. 内容总结 本章回是一起Talk AndroidJetpack吧专栏的第一章回&#xff0c;本章回中主要介绍JetPack的基本概念和编程思想&#xff0c;同时也会介绍它的基础知识。闲话休提&#xff0c;请我们一起Talk Andr…

Mysql——创建数据库,对表的创建及字段定义、数据录入、字段增加及删除、重命名表。

一.创建数据库 create database db_classics default charsetutf8mb4;//创建数据库 use db_classics;//使用该数据库二.对表的创建及字段定义 create table if not exists t_hero ( id int primary key auto_increment, Name varchar(100) not null unique, Nickname varchar(1…

TDengine OSS 与 qStudio 实现无缝协同,革新数据分析和管理方式

在数字化转型如火如荼的当下&#xff0c;海量爆发的时序数据处理成为转型成功的关键因素之一。为了帮助社区用户更好地进行数据分析和管理&#xff0c;丰富可视化解决方案的多样性&#xff0c;我们将开源的时序数据库&#xff08;Time Series Database&#xff09; TDengine OS…

【Zookeeper专题】Zookeeper经典应用场景实战(一)

目录 前置知识课程内容一、Zookeeper Java客户端实战1.1 Zookeeper 原生Java客户端使用1.2 Curator开源客户端使用快速开始使用示例 二、Zookeeper在分布式命名服务中的实战2.1 分布式API目录2.2 分布式节点的命名2.3 分布式的ID生成器 三、zookeeper实现分布式队列3.1 设计思路…

SpringBoot集成MyBatis-Plus实现增删改查

背景 因为学习工具的时候经常需要用到jar包&#xff0c;需要增删查改接口&#xff0c;所以参考文章实现了基于mybatis-plus的增删查改接口。 参考文章&#xff1a;第二十二节:SpringBoot集成MyBatis-Plus实现增删改查 原文中的git地址不存在&#xff0c;本文内容是原文代码修…

基于Java的源代码共享平台设计与实现(源码+lw+ppt+部署文档+视频讲解等)

文章目录 前言系统功能具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域…

C#学习系列相关之多线程(二)----Thread类介绍

一、线程初始化 1.无参数 static void Main(string[] args) {//第一种写法Thread thread new Thread(test);thread.Start();//第二种写法 delegateThread thread1 new Thread(new ThreadStart(test));thread1.Start();//第三种写法 lambdaThread thread2 new Thread(() >…

R语言提交后台任务Rstudio\nohup

R语言后台任务用法 在进行大规模数据分析时&#xff0c;R语言提供了后台计算的功能&#xff0c;能将计算任务提交到后台执行&#xff0c;不影响当前窗口的活动&#xff0c;而且不会受到网络波动导致任务中断&#xff0c;提交后就不用盯着一直看&#xff0c;后台运行就可以下班。…

3.1.OpenCV技能树--二值图像处理--阈值

文章目录 1.文章内容来源2.阈值分割2.1.简单阈值分割2.1.1.简单阈值分割原理介绍2.1.2.简单阈值分割核心代码2.1.3.简单阈值分割效果展示 2.2.自适应阈值分割2.2.1.自适应阈值分割原理介绍2.2.2.自适应阈值分割核心代码2.2.3.自适应阈值分割效果展示 2.3.Otsu’s二值化/大津阈值…

指针拔尖1——(看完包会,不会来打我)

文章目录 前言&#xff1a;本章节涵盖——一、指针变量基础二、字符指针三、指针数组和数组指针拓展&#xff1a;数组名和&数组名的区别四、 指针传参总结 前言&#xff1a;本章节涵盖—— 1.指针变量基础知识 2.字符指针 3.数组指针 4.指针数组 5.指针传参 一、指针变量基…