当前位置: 首页 > news >正文

分布式锁redis

工具类

package com.ruoyi.zlzh.spmms.util;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;/*** Redis分布式锁服务** @author yxy*/
@Component
public class RedisLockService {@Resourceprivate RedisTemplate redisTemplate;private static final String LOCK_PREFIX = "redis_lock:";private static final String UNLOCK_LUA_SCRIPT ="if redis.call('get', KEYS[1]) == ARGV[1] then " +"return redis.call('del', KEYS[1]) " +"else " +"return 0 " +"end";/*** 尝试获取锁** @param lockKey    锁的key* @param expireTime 锁的过期时间* @param timeUnit   时间单位* @return 锁的值,获取失败返回null*/public String tryLock(String lockKey, long expireTime, TimeUnit timeUnit) {String lockValue = UUID.randomUUID().toString();String key = LOCK_PREFIX + lockKey;Boolean success = redisTemplate.opsForValue().setIfAbsent(key, lockValue, expireTime, timeUnit);return Boolean.TRUE.equals(success) ? lockValue : null;}/*** 释放锁** @param lockKey   锁的key* @param lockValue 锁的值* @return 是否释放成功*/public boolean releaseLock(String lockKey, String lockValue) {String key = LOCK_PREFIX + lockKey;DefaultRedisScript<Long> script = new DefaultRedisScript<>();script.setScriptText(UNLOCK_LUA_SCRIPT);script.setResultType(Long.class);Long result = (Long) redisTemplate.execute(script, Collections.singletonList(key), lockValue);return Long.valueOf(1).equals(result);}/*** 执行带锁的操作** @param lockKey    锁的key* @param expireTime 锁的过期时间* @param timeUnit   时间单位* @param supplier   要执行的操作* @param <T>        返回值类型* @return 操作结果* @throws RuntimeException 获取锁失败时抛出异常*/public <T> T executeWithLock(String lockKey, long expireTime, TimeUnit timeUnit, Supplier<T> supplier) {String lockValue = tryLock(lockKey, expireTime, timeUnit);if (lockValue == null) {throw new RuntimeException("获取分布式锁失败,请稍后重试");}try {return supplier.get();} finally {releaseLock(lockKey, lockValue);}}/*** 执行带锁的操作(默认30秒过期时间)** @param lockKey  锁的key* @param supplier 要执行的操作* @param <T>      返回值类型* @return 操作结果  这个默认30秒 感觉不太好 一般2到3秒*/public <T> T executeWithLock(String lockKey, Supplier<T> supplier) {return executeWithLock(lockKey, 3, TimeUnit.SECONDS, supplier);}
}

使用

@Autowiredprivate RedisLockService redisLockService;@Overridepublic int updateSpMrItem(SpMrItem spMrItem) {// 使用分布式锁保护并发更新String lockKey = "mr_item_update_" + spMrItem.getMrItemId();return redisLockService.executeWithLock(lockKey, () -> {// 获取数据库中的原始记录SpMrItem originalItem = spMrItemMapper.selectSpMrItemByMrItemId(spMrItem.getMrItemId());// 是否唯一if (StringUtils.isNotEmpty(spMrItem.getItemNo())) {if (!spMrItem.getItemNo().equals(originalItem.getItemNo())) {int count = spMrItemMapper.checkItemNoUnique(spMrItem.getItemNo(),spMrItem.getMrId());if (count > 0) {throw new RuntimeException("MR物料条目号已存在,请使用其他");}}}// 检查数量是否发生变化if (originalItem != null && spMrItem.getQty() != null && originalItem.getQty() != null) {// 如果数量发生了变化if (!spMrItem.getQty().equals(originalItem.getQty())) {// 将原来的数量保存到previousQtyspMrItem.setPreviousQty(originalItem.getQty());// 增加变更次数Integer currentChangeCount = originalItem.getChangeCount();if (currentChangeCount == null) {currentChangeCount = 0;}spMrItem.setChangeCount(currentChangeCount + 1);}}spMrItem.setUpdateTime(DateUtils.getNowDate());spMrItem.setUpdateBy(SecurityUtils.getUsername());return spMrItemMapper.updateSpMrItem(spMrItem);});}

文章转载自:

http://oSJi3DpX.rnjgh.cn
http://4DqT4YaU.rnjgh.cn
http://B7gd4QNJ.rnjgh.cn
http://O6IybRPQ.rnjgh.cn
http://1voSM3Yn.rnjgh.cn
http://1X8xG6Ju.rnjgh.cn
http://eMgXIO4V.rnjgh.cn
http://oRnMc0z4.rnjgh.cn
http://6USDgxGn.rnjgh.cn
http://PwadEXxo.rnjgh.cn
http://l17VK7S0.rnjgh.cn
http://zUqf2aCj.rnjgh.cn
http://kAAGQtFS.rnjgh.cn
http://nWYUShWK.rnjgh.cn
http://BQPjN0HG.rnjgh.cn
http://kiRpcoLC.rnjgh.cn
http://v8CWse5w.rnjgh.cn
http://cP5sEI1W.rnjgh.cn
http://V5gK5j0G.rnjgh.cn
http://ycZpoTCn.rnjgh.cn
http://Gbiki133.rnjgh.cn
http://pVjFzg9C.rnjgh.cn
http://QZEHr6B6.rnjgh.cn
http://3bzO8IKk.rnjgh.cn
http://S8STmqHt.rnjgh.cn
http://7mW0eSHI.rnjgh.cn
http://3LhQJlxM.rnjgh.cn
http://tSsMSvk9.rnjgh.cn
http://fmaDlgPW.rnjgh.cn
http://IVa6m5mI.rnjgh.cn
http://www.dtcms.com/a/375563.html

相关文章:

  • Java学习之——“IO流“的进阶流之转换流的学习
  • git 如何直接拉去远程仓库的内容且忽略本地与远端不一致的commit
  • 每日一算:分发糖果
  • 神经算子学习
  • AI大模型入门1.1-python基础字符串代码
  • Tlias管理系统(多表查询-内连接外连接)
  • win11家庭版配置远程桌面
  • 8. LangChain4j + 提示词工程详细说明
  • ChatGPT大模型训练指南:如何借助动态代理IP提高训练效率
  • 利用git进行版本控制
  • 深入理解synchronized:从使用到原理的进阶指南
  • 第八章 矩阵按键实验
  • 【CSS 3D 实战】从零实现旋转立方体:理解 3D 空间的核心原理
  • C++互斥锁使用详解与案例分析
  • Python+DRVT 从外部调用 Revit:批量创建柱
  • Matlab机器人工具箱6.2 导入stl模型——用urdf文件描述
  • 网页设计模板 HTML源码网站模板下载
  • 南京大学计算机学院 智能软件工程导论 + Luciano Baresi 教授讲座
  • Rust/C/C++ 混合构建 - Buck2构建工具一探究竟
  • Drawnix:开源一体化白板工具,让你的创意无限流动!
  • stm32 链接脚本没有 .gcc_except_table 段也能支持 C++ 异常
  • K8S集群管理(4)
  • flutter TabBar 设置isScrollable 第一个有间距
  • 学习 Android (二十一) 学习 OpenCV (六)
  • Maven项目中修改公共依赖项目并发布到nexus供三方引用全流程示例
  • GD32VW553-IOT开发板移植适配openharmony
  • nuxt3在使用vue-echarts报错 document is not defined
  • 嵌入式第四十九天(ARM汇编指令)
  • RS485通信 , 和modus RTU
  • 7. LangChain4j + 记忆缓存详细说明