记一个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,完全是手动实现的 我 ...
随机推荐
- Qt Examples - Boxes (在Qt场景视图中结合OpenGL渲染)
QT自带例程Boxes使用QT Graphics View框架实现了2D图形和3D图形的混合渲染,综合性比较强,整合知识较多,值得学习. 可以使用鼠标通过以下方式控制演示中的元素: 按住鼠标左键的同时 ...
- springboot 启动停止脚本
https://www.cnblogs.com/lovychen/p/6211209.html 参考 centos 转码解决方案: yum install dos2unix dos2unix ** ...
- 机器学习之KMeans聚类
零.学习生成测试数据 from sklearn.datasets import make_blobs from matplotlib import pyplot # create test data ...
- Docker在Centos 7上的部署
Docker在Centos 7上的部署 方法1---开启centos 7上自带的 extras YUM源,然后 yum install docker来安装 安装前必须保证 Linux Kernel ...
- PHP redis 常用操作
//在列表头部插入一个值one,当列表不存在时自动创建一个列表,key1为列表名 $redis->lpush("key1", "one"); //在列表尾 ...
- Codeforces A. Playlist(暴力剪枝)
题目描述: Playlist time limit per test 2 seconds memory limit per test 256 megabytes input standard inpu ...
- 遇到libgflags.a(gflags.cc.o): relocation R_X86_64_32 against `.rodata.str1.1' ca时
glfag编译成动态库gflags 正确的安装方法是这样的: Need cmake >2.8.4 (current is 2.8.3) mkdir build cd build cmake -D ...
- shell脚本如何判断文件大小
转自:https://blog.csdn.net/lovegengxin/article/details/80762329 1 .ls -lls -l $filename | awk '{print ...
- I/O管理杂记
这是一篇杂记,记录了操作系统层面与I/O管理的零散知识点,用于温习使用.由于I/O管理是一个很大的范畴,后续会不断按照自己的生产需求来补充用的到的知识点.计算机系统是人造系统,没有绝对的对错(相对于自 ...
- Codeforces Round 563 (Div. 2) 题解
自己开了场镜像玩. 前三题大水题.D有点意思.E完全不会.F被题意杀了……然而还是不会. 不过看过(且看懂)了官方题解,所以这里是六题题解齐全的. A 水题.给原序列排序,如果此时合法则直接输出,否则 ...