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. xamarin Mqtt

    1 什么是MQTT? mqtt (Message Queuing Telemetry Transport,消息队列遥测传输)是 IBM 开发的一个即时通讯协议,有可能成为物联网的重要组成部分.MQTT ...

  2. ffmpeg 基本数据结构和对象(一): AVPacket、AVPicture、AVFrame

    来源:http://blog.csdn.net/chance_yin/article/details/16817957 一.AVPacket /** * AVPacket 作为解码器的输入 或 编码器 ...

  3. SAP云平台和第三方CRM解决方案(火锅)互联

    光看封面配图,这篇文章很容易被误认为在讲成都的美食之一:火锅. SAP成都研究院坐落在被联合国教科文组织授予过"美食之都"称号的成都,所在的天府软件园,半径1公里左右星罗棋布着很多 ...

  4. PHP查询附近的人及其距离的实现方法

    1.附近的人 //获取该点周围的4个点 $distance = 1;//范围(单位千米) $lat = 113.873643; $lng = 22.573969; define('EARTH_RADI ...

  5. elastic常用工具

    elasticsearch 常用工具: elasticsearch-dump :备份 elasticsearch-head :数据展示.操作平台 elasticsearch-head github 地 ...

  6. 浅析Volatile关键字

    浅析Volatile关键字 在java中线程并发中,线程之间通信方式分为两种:共享内存和消息传递.共享内存指的是多个线程之间共享内存的属性状态:消息传递指的是线程之间发送信息来通信.在介绍volati ...

  7. nginx 请求限制

    1.nginx 请求限制 1.连接频率限制 - limit_conn_module 2.请求频率限制 - limit_req_module 连接限制的语法 请求限制的语法 limit_conn_zon ...

  8. views视图

    1.request.POST.get('.......')    --radio       单选框 get()方法  从HTML中提取发过来的数据 1. 2. 3. 4. 2.request.POS ...

  9. blocking cache和non-blocking cache

    - a Blocking Cache will not accept any more request until the miss is taken care of. - a Non-blockin ...

  10. 攻防世界(Ctf-Web 新手练习区)

    题目:view_source 在url的前面加上个 “view-source: ”就看到flag了,或者“CTRL+U”快捷键查看源码 flag:cyberpeace{e07dcafaeeb31df2 ...