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分布式事务锁的更多相关文章

  1. 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...

  2. 利用redis实现分布式事务锁,解决高并发环境下库存扣减

    利用redis实现分布式事务锁,解决高并发环境下库存扣减   问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...

  3. .net core 下的分布式事务锁

    原文:.net core 下的分布式事务锁 目录 系统分布式锁的用法 锁的实现 锁的使用 API内的范例: 引用链接 系统分布式锁的用法 公司框架新增功能分布式锁: 锁的性能之王: 缓存 > Z ...

  4. 关于如何实现一个Saga分布式事务框架的思考

    关于Saga模式的介绍,已经有一篇文章介绍的很清楚了,链接在这里:分布式事务:Saga模式. 关于TCC模式的介绍,也已经有一篇文章介绍的很清楚了,链接在这里:关于如何实现一个TCC分布式事务框架的一 ...

  5. 聊一聊如何用C#轻松完成一个SAGA分布式事务

    背景 银行跨行转账业务是一个典型分布式事务场景,假设 A 需要跨行转账给 B,那么就涉及两个银行的数据,无法通过一个数据库的本地事务保证转账的 ACID ,只能够通过分布式事务来解决. 市面上使用比较 ...

  6. 聊一聊如何用C#轻松完成一个TCC分布式事务

    背景 银行跨行转账业务是一个典型分布式事务场景,假设 A 需要跨行转账给 B,那么就涉及两个银行的数据,无法通过一个数据库的本地事务保证转账的 ACID ,只能够通过分布式事务来解决. 在 聊一聊如何 ...

  7. Zookeeper 分布式事务锁的使用

    使用Netflix的包 curator-recipes pom文件引入相关依赖 <dependency> <groupId>org.apache.zookeeper</g ...

  8. Redis分布式锁—Redisson+RLock可重入锁实现篇

    前言 平时的工作中,由于生产环境中的项目是需要部署在多台服务器中的,所以经常会面临解决分布式场景下数据一致性的问题,那么就需要引入分布式锁来解决这一问题. 针对分布式锁的实现,目前比较常用的就如下几种 ...

  9. redis分布式锁实践

    分布式锁在多实例部署,分布式系统中经常会使用到,这是因为基于jvm的锁无法满足多实例中锁的需求,本篇将讲下redis如何通过Lua脚本实现分布式锁,不同于网上的redission,完全是手动实现的 我 ...

随机推荐

  1. 【python】ConnectionRefusedError: [WinError 10061]

    在测试接口过程中,由于各种原因服务端返回:10061,由于目标计算机积极拒绝,无法连接. 图一 图二 造成这种返回结果的可能原因:1.代码问题2.本机代理设置问题3.本地防火墙或者安全卫士之类的设置问 ...

  2. 面试官问我,为什么老司机建议MySQL列属性尽量用 NOT NULL ?

    本文阅读时间大约6分钟. 其实写这篇文章,也是来自一个知识星球读者的提问,他在二面的过程中被问到了,由于他简历中写道有 MySQL 调优经验,但这个问题没有回答好,二面被刷了. 其实我们刚学习 C 语 ...

  3. CDA数据分析【数据处理工具SPSS】

    一.概述 SPSS[Statistical Package for the Social Science]社会科学统计软件包.SPSS统计软件在社会学.经济学.心理学.教育学等多个学科的研究工作和通信 ...

  4. rac启动维护笔记

    Ohasd.bin将产生4个代理启动相关的资源 (1)    oraagent:负责ora.asm.ora.evmd.ora.gipcd.ora.gpnpd.ora.mdnsd的启动和管理 (2)   ...

  5. SQL Server 修改表结构(转载)

    SQL Server 修改表结构 本文链接:https://blog.csdn.net/petezh/article/details/81744374 查看指定表结构 exec sp_help Rep ...

  6. MySQL数据库(六)-- SQL注入攻击、视图、事物、存储过程、流程控制

    一.SQL注入攻击 1.什么是SQL注入攻击 一些了解sql语法的用户,可以输入一些关键字 或合法sql,来导致原始的sql逻辑发生变化,从而跳过登录验证 或者 删除数据库 import pymysq ...

  7. Odoo treeView列表视图详解

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826414.html TreeView:列表视图 1:<tree>标签的属性 [tree标签内 ...

  8. rollup入门

    作为js程序员,掌握rollup是必要的. 有了webpack后,为什么还要用rollup, 因为webpack不专业,webpack是打包一切. rollup只为打包js而生. rollup通过的五 ...

  9. 性能测试基础---jmeter参数化、关联、事物、检查的等

    ·Jmeter脚本增强·性能测试的脚本增强技术:参数化.关联.事务.检查点.思考时间和集合点. ·参数化:在Jmeter中,实现参数化的方式很多.本质上来说,参数化的实现方式有两种:·文件方式:一般建 ...

  10. C#进阶系列 ---- 《CLR via C#》

      [C#进阶系列]30 学习总结 [C#进阶系列]29 混合线程同步构造 [C#进阶系列]28 基元线程同步构造 [C#进阶系列]27 I/O限制的异步操作 [C#进阶系列]26 计算限制的异步操作 ...