记一个Redis分布式事务锁
package com.mall.common; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
@Slf4j
public class DisLock {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// RedisTemplate
public void oneLock(){
String key = "key-001";
Long currentTime = System.currentTimeMillis();
boolean lock = redisTemplate.opsForValue().setIfAbsent(key, currentTime);
try {
if (lock) {
log.info("获取锁成功,开始逻辑处理");
}else{
log.info("获取锁失败,业务正在处理中,请稍后");
}
}catch (Exception e){
log.error("系统异常",e);
}finally {
if (lock) {
redisTemplate.delete(key);
log.info("处理结束,释放锁!");
} else {
log.info("没有获取到锁,无需释放锁!");
Long createTime = (Long) redisTemplate.opsForValue().get(key);
Long nowTime = System.currentTimeMillis();
Long time = (nowTime - createTime) / 1000;
log.info("没有获取到锁,检测获取锁的线程是否处理超时,超时则释放他的锁");
if (time > 10) {//自定义锁多久自动释放锁
redisTemplate.delete(key);
log.info("逻辑处理超过20秒,释放锁!");
}
}
}
}
//jds
public void twoLock() {
//基于redis的分布式锁
String redisKey = "key-001";
boolean falg = false;
try {
Long lock = this.incrBy(redisKey, 1, 10);//一次,超时时间10秒
if (lock > 1) {
log.info("请勿重复提交请求");
}
log.info("逻辑处理开始。。。。");
} catch (Exception e) {
log.error("#accumulatePoints() 出现异常:{}", e);
} finally {
if(falg) {
this.del(redisKey);
}
}
} static ShardedJedisPool pool;
public static Long incrBy(String key, long num, int seconds) {
ShardedJedis jds = null;
jds = pool.getResource();
Long result = jds.incrBy(key, num);
if (seconds > 0) {
jds.expire(key, seconds);
}
return result;
}
public static void del(String key) {
ShardedJedis jds = null;
try {
jds = pool.getResource();
jds.del(key);
} catch (Exception e) {
log.error("#RedisPool() del异常:", e);
e.printStackTrace(); }
} }
package com.redis.mq.util; import redis.clients.jedis.Jedis; import java.util.Collections;
import java.util.UUID; /**
* @author xiaowu
* @date 2019-12-20
**/
public class RedisLock {
/**
* RedisLock的正确姿势
* 加锁:
* 通过setnx 向特定的key写入一个随机数,并设置失效时间,写入成功即加锁成功
* 注意点:
* 必须给锁设置一个失效时间 -----> 避免死锁
* 加锁时,每个节点产生一个随机字符串 -----> 避免锁误删
* 写入随机数与设置失效时间必须是同时 -----> 保证加锁的原子性
* 使用:
* SET key value NX PX 3000
*
* 解锁:
* 匹配随机数,删除redis上的特定的key数据,
* 要保证获取数据,判断一致以及删除数据三个操作是原子性
* 执行如下lua脚本:
* if redis.call('get', KEYS[1]) == ARGV[1] then
* return redis.call('del', KEYS[1])
* else
* return 0
* end
*
*/
// 使用jedis 客户端的
/**SET key value NX PX 3000 成功返回值*/
private static final String LOCK_SUCCESS = "OK";
/**表示 NX 模式*/
private static final String SET_IF_NOT_EXIST = "NX";
/**单位 毫秒**/
private static final String SET_WITH_EXPIRE_TIME_PX = "PX";
/**lua脚本**/
private static final String SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
/**存储随机数**/
private static final ThreadLocal<String> local = new ThreadLocal<>();
/**
* 加锁
*/
public static boolean lock(Jedis jedis, String key, int expireTime) {
// 产生随机数
String uuid = UUID.randomUUID().toString().replaceAll("-", ""); String result = jedis.set(key, uuid, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME_PX, expireTime); if (LOCK_SUCCESS.equals(result)) {
// 随机数绑定线程
local.set(uuid);
return true;
}
return false;
} /**
* 释放分布式锁
*/
public static boolean unLock(Jedis jedis, String key) { String uuid = local.get();
//当前线程没有绑定uuid
//直接返回
if (uuid == null || "".equals(uuid)) {
return false;
} Object result = jedis.eval(SCRIPT, Collections.singletonList(key), Collections.singletonList(uuid)); if (Long.valueOf(1).equals(result)) {
// 解除绑定线程的随机数
local.remove();
return true;
}
return false;
} public static void main(String[] args) {
Jedis jedis = new Jedis("localhost", 6379);
jedis.auth("373616885");
jedis.select(0);
final String LOCK_KEY = "LOCK_KEY";
RedisLock.lock(jedis,LOCK_KEY,5000);
RedisLock.unLock(jedis,LOCK_KEY);
} }
记一个Redis分布式事务锁的更多相关文章
- 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存
原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...
- 利用redis实现分布式事务锁,解决高并发环境下库存扣减
利用redis实现分布式事务锁,解决高并发环境下库存扣减 问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...
- .net core 下的分布式事务锁
原文:.net core 下的分布式事务锁 目录 系统分布式锁的用法 锁的实现 锁的使用 API内的范例: 引用链接 系统分布式锁的用法 公司框架新增功能分布式锁: 锁的性能之王: 缓存 > Z ...
- 关于如何实现一个Saga分布式事务框架的思考
关于Saga模式的介绍,已经有一篇文章介绍的很清楚了,链接在这里:分布式事务:Saga模式. 关于TCC模式的介绍,也已经有一篇文章介绍的很清楚了,链接在这里:关于如何实现一个TCC分布式事务框架的一 ...
- 聊一聊如何用C#轻松完成一个SAGA分布式事务
背景 银行跨行转账业务是一个典型分布式事务场景,假设 A 需要跨行转账给 B,那么就涉及两个银行的数据,无法通过一个数据库的本地事务保证转账的 ACID ,只能够通过分布式事务来解决. 市面上使用比较 ...
- 聊一聊如何用C#轻松完成一个TCC分布式事务
背景 银行跨行转账业务是一个典型分布式事务场景,假设 A 需要跨行转账给 B,那么就涉及两个银行的数据,无法通过一个数据库的本地事务保证转账的 ACID ,只能够通过分布式事务来解决. 在 聊一聊如何 ...
- Zookeeper 分布式事务锁的使用
使用Netflix的包 curator-recipes pom文件引入相关依赖 <dependency> <groupId>org.apache.zookeeper</g ...
- Redis分布式锁—Redisson+RLock可重入锁实现篇
前言 平时的工作中,由于生产环境中的项目是需要部署在多台服务器中的,所以经常会面临解决分布式场景下数据一致性的问题,那么就需要引入分布式锁来解决这一问题. 针对分布式锁的实现,目前比较常用的就如下几种 ...
- redis分布式锁实践
分布式锁在多实例部署,分布式系统中经常会使用到,这是因为基于jvm的锁无法满足多实例中锁的需求,本篇将讲下redis如何通过Lua脚本实现分布式锁,不同于网上的redission,完全是手动实现的 我 ...
随机推荐
- 无线安全审计工具FruityWifi初体验
FruityWIfi是一款有名的无线安全审计的开源工具,其灵感来自于wifipineapple,目前该工具已经更新到2.4.它能够让用户通过web界面来控制和管理模块,十分方便.FriutyWifi最 ...
- kingbase常用语句
1. 查询数据库名 # select * from SYS_DATABASE; 2. 查询模式名 # select * from SYS_NAMESPACE; 3. 查询表空间 # select * ...
- Spark调用Linux命令实现解压和压缩功能
一.应用场景 在Spark程序中调用Linux命令,实现一些程序难以实现的功能,例如:发送模拟邮件.文件打包或解压等等 二.代码实现 package big.data.analyse.linux im ...
- Mysql数据库之慢查询
一.简介 开启慢查询日志,可以让MySQL记录下查询超过指定时间的语句,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能. 二.参数说明 slow_query_log 慢查询开启状态 slow_ ...
- Nginx 核心配置-作为上传服务器配置
Nginx 核心配置-作为上传服务器配置 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.关键参数说明 client_max_body_size 1m: 设置允许客户端上传单 ...
- dapi 基于Django的轻量级测试平台三 接口关联
QQ群: GitHub:https://github.com/yjlch1016/dapi 一.接口关联思路: 在接口测试中, 很多场景下, 上一个接口的出参要作为下一个接口的入参, 即上一个接口的响 ...
- LCD硬件原理
想象一下,屏幕的后面有一个电子枪,电子枪位于某个像素的背后,然后向这个像素发射红绿蓝三原色,从而就可以组成任意一种颜色.简单的说,电子枪在像素的背后一边移动,一边向像素发射红绿蓝. 如果要编写出LCD ...
- Navicat Premium 12 永久使用办法
1.按步骤安装Navicat Premium,如果没有可以去官网下载:http://www.navicat.com.cn/download/navicat-premium 2.安装好后下载激活文件:h ...
- unity客户端自动断开连接
问题描述: 当unity失去焦点一段时间后,与photon服务器端断开连接 问题根源: 默认unity失去焦点后会暂停运行,导致连接超时,服务器端超时断开连接 解决方案: 连接服务器后,填加一句代码让 ...
- sublime ctrl b突然不能用解决方法
Sublime Text 2 ?ctrl+b 如果出现运行为空白,按ctrl+`来显示错误,如下所示,转载了一篇解决方案 ? 文章参考:http://eric.themoritzfamily.com/ ...