使用redis的setnx命令进行实现

@Component
@Slf4j
public class RedisLock {
@Autowired
private StringRedisTemplate stringRedisTemplate; /**
* 加锁
*
* @param key
* @param value
* @return
*/
public boolean lock(String key, String value) {
if (stringRedisTemplate.opsForValue().setIfAbsent(key, value)) {
return true;
}
String currentValue = stringRedisTemplate.opsForValue().get(key);
//防止死锁
if (!StringUtils.isEmpty(currentValue)
&& Long.parseLong(currentValue) < System.currentTimeMillis()) {
String oldValue = stringRedisTemplate.opsForValue().getAndSet(key, value);
if (!StringUtils.isEmpty(oldValue)
&& oldValue.equals(currentValue)) {
return true;
} }
return false;
} /**
* 解锁
* @param key
* @param value
*/
public void unlock(String key, String value) {
try {
String currentValue = stringRedisTemplate.opsForValue().get(key);
if (!StringUtils.isEmpty(currentValue)
&& currentValue.equals(value)) {
stringRedisTemplate.opsForValue().getOperations().delete(key);
}
} catch (Exception e) {
log.error("【redis分布式锁】 解锁异常,{}", e);
} }
}

demo

@Service
public class SecKillServiceImpl implements SeckillService {
//超时时间10秒
private static final int TIMEOUT = 10 * 1000;
@Autowired
private RedisLock redisLock; static Map<String, Integer> products;
static Map<String, Integer> stock;
static Map<String, String> orders; {
products = new HashMap<>();
stock = new HashMap<>();
orders = new HashMap<>();
products.put("123456", 100000);
stock.put("123456", 100000);
} private String queryMap(String productId) {
return "国庆活动,皮蛋粥特价,限量份"
+ products.get(productId)
+ "还剩:" + stock.get(productId) + "份"
+ "该商品成功下单用户数目:"
+ orders.size() + "人";
} @Override
public void orderProductMockDiffUser(String productId) {
Long time = System.currentTimeMillis() + TIMEOUT;
//加锁
if (!redisLock.lock(productId, String.valueOf(time))) {
throw new SellException(101, "哎呦喂,人也太多了,在试试");
} Integer stockNum = stock.get(productId);
if (stockNum == 0) {
throw new SellException(100, "活动结束");
} else {
//下单
orders.put(KeyUtil.genUniqueKey(), productId);
//减库存
stockNum = stockNum - 1;
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
stock.put(productId, stockNum);
}
//解锁
redisLock.unlock(productId, String.valueOf(time));
} @Override
public String querySecKillProductInfo(String productId) {
return queryMap(productId);
}
}

浅谈redis分布式锁用法的更多相关文章

  1. Redis分布式锁的原理和实现

    前言 我们之前聊过redis的,对基础不了解的可以移步查看一下: 几分钟搞定redis存储session共享--设计实现:https://www.cnblogs.com/xiongze520/p/10 ...

  2. redis分布式锁和消息队列

    最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令. 分布式锁 由于目前一些编程语言,如PHP ...

  3. Redis分布式锁的try-with-resources实现

    Redis分布式锁的try-with-resources实现 一.简介 在当今这个时代,单体应用(standalone)已经很少了,java提供的synchronized已经不能满足需求,大家自然 而 ...

  4. 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁

    首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...

  5. Redlock:Redis分布式锁最牛逼的实现

    普通实现 说道Redis分布式锁大部分人都会想到:setnx+lua,或者知道set key value px milliseconds nx.后一种方式的核心实现命令如下: - 获取锁(unique ...

  6. $.ajax()方法详解 ajax之async属性 【原创】详细案例解剖——浅谈Redis缓存的常用5种方式(String,Hash,List,set,SetSorted )

    $.ajax()方法详解   jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为Str ...

  7. 五分钟DBA:浅谈伪分布式数据库架构

    [IT168 技术]12月25日消息,2010互联网行业技术研讨峰会今日在上海华东理工大学召开.本次峰会以“互联网行业应用最佳实践”为主题,定位于互联网架构设计.应用开发.应用运维管理,同时,峰会邀请 ...

  8. 面试官:你真的了解Redis分布式锁吗?

    什么是分布式锁 说到Redis,我们第一想到的功能就是可以缓存数据,除此之外,Redis因为单进程.性能高的特点,它还经常被用于做分布式锁. 锁我们都知道,在程序中的作用就是同步工具,保证共享资源在同 ...

  9. Redis分布式锁升级版RedLock及SpringBoot实现

    分布式锁概览 在多线程的环境下,为了保证一个代码块在同一时间只能由一个线程访问,Java中我们一般可以使用synchronized语法和ReetrantLock去保证,这实际上是本地锁的方式.但是现在 ...

随机推荐

  1. 设置terminal 命令别名

    vi -/.bash_profile code () { VSCODE_CWD="$PWD" open -n -b "com.microsoft.VSCode" ...

  2. java:Mybatis框架3(二级缓存,延时和积极加载,SSI(Ibatis)集成,SSM集成)

    1.二级缓存: 需要导入二级缓存jar包: mybatis03: ehcache.xml: <ehcache xmlns:xsi="http://www.w3.org/2001/XML ...

  3. (转)JMeter性能测试-服务器资源监控插件详解

    零.引言 我们对被测应用进行性能测试时,除了关注吞吐量.响应时间等应用自身的表现外,对应用运行所涉及的服务器资源的使用情况,也是非常重要的方面,通过实时监控,可以准确的把握不同测试场景下服务器资源消耗 ...

  4. excel常用公式--数据清洗类

    trim:去除单元格两端的空格. concat/&:连接单元格内的内容. mid:  提取字符串中间的字符串. left:  提取字符串左边的字符串. right: 提取字符串右边的字符串. ...

  5. spring boot1.1 idea + springboot + mybatis(mybatis-generator) +mysql +html实现简单的登录注册

    前言 这两年springboot比较火,而我平时的工作中不怎么使用spring boot,所以工作之余就自己写写项目练练手,也跟大家一起学习. 打算从最开始的搭架子,登录注册,到后台管理的增删改查,业 ...

  6. C++ day01 预备知识、C++综述、教材、推荐阅读。

    C++ day01: 1.预备知识? 1)什么是编程 编程,即编订程序. 程序 = 数据 + 算法(蛋糕 = 糖.鸡蛋.奶油 + 打鸡蛋.加糖.烤) 2)编程语言 最初的编程是用二进制代码(即“机器码 ...

  7. python-day12(正式学习)

    目录 可变长参数 可变长形参之* 可变长实参之* 可变长形参之** 可变长实参之** 可变长参数应用 命名关键字形参 函数对象 四大功能 引用 当作参数传给一个函数 可以当作函数的返回值 可以当作容器 ...

  8. numpy-查找操作大全

    本文记录日常工作中遇到的查找操作,持续更新. 注意:输入必须是 数组,不能是 list 极值 min,max 返回极值 argmin(a, axis=None, out=None), 返回极值所在的位 ...

  9. mybatis工作原理及实现

    对数据库的连接 使用时就创建连接,不使用就立即释放,对数据库进行频繁连接开启和关闭,造成数据库的资源浪费,影响数据库的性能: 解决办法:使用数据库连接池,管理数据库的连接. 2 将sql语句硬编码到j ...

  10. RabbitMQ入门教程(一):安装和常用命令

    原文:RabbitMQ入门教程(一):安装和常用命令 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn ...