使用redis的setnx命令进行实现

  1. @Component
  2. @Slf4j
  3. public class RedisLock {
  4. @Autowired
  5. private StringRedisTemplate stringRedisTemplate;
  6.  
  7. /**
  8. * 加锁
  9. *
  10. * @param key
  11. * @param value
  12. * @return
  13. */
  14. public boolean lock(String key, String value) {
  15. if (stringRedisTemplate.opsForValue().setIfAbsent(key, value)) {
  16. return true;
  17. }
  18. String currentValue = stringRedisTemplate.opsForValue().get(key);
  19. //防止死锁
  20. if (!StringUtils.isEmpty(currentValue)
  21. && Long.parseLong(currentValue) < System.currentTimeMillis()) {
  22. String oldValue = stringRedisTemplate.opsForValue().getAndSet(key, value);
  23. if (!StringUtils.isEmpty(oldValue)
  24. && oldValue.equals(currentValue)) {
  25. return true;
  26. }
  27.  
  28. }
  29. return false;
  30. }
  31.  
  32. /**
  33. * 解锁
  34. * @param key
  35. * @param value
  36. */
  37. public void unlock(String key, String value) {
  38. try {
  39. String currentValue = stringRedisTemplate.opsForValue().get(key);
  40. if (!StringUtils.isEmpty(currentValue)
  41. && currentValue.equals(value)) {
  42. stringRedisTemplate.opsForValue().getOperations().delete(key);
  43. }
  44. } catch (Exception e) {
  45. log.error("【redis分布式锁】 解锁异常,{}", e);
  46. }
  47.  
  48. }
  49. }

demo

  1. @Service
  2. public class SecKillServiceImpl implements SeckillService {
  3. //超时时间10秒
  4. private static final int TIMEOUT = 10 * 1000;
  5. @Autowired
  6. private RedisLock redisLock;
  7.  
  8. static Map<String, Integer> products;
  9. static Map<String, Integer> stock;
  10. static Map<String, String> orders;
  11.  
  12. {
  13. products = new HashMap<>();
  14. stock = new HashMap<>();
  15. orders = new HashMap<>();
  16. products.put("123456", 100000);
  17. stock.put("123456", 100000);
  18. }
  19.  
  20. private String queryMap(String productId) {
  21. return "国庆活动,皮蛋粥特价,限量份"
  22. + products.get(productId)
  23. + "还剩:" + stock.get(productId) + "份"
  24. + "该商品成功下单用户数目:"
  25. + orders.size() + "人";
  26. }
  27.  
  28. @Override
  29. public void orderProductMockDiffUser(String productId) {
  30. Long time = System.currentTimeMillis() + TIMEOUT;
  31. //加锁
  32. if (!redisLock.lock(productId, String.valueOf(time))) {
  33. throw new SellException(101, "哎呦喂,人也太多了,在试试");
  34. }
  35.  
  36. Integer stockNum = stock.get(productId);
  37. if (stockNum == 0) {
  38. throw new SellException(100, "活动结束");
  39. } else {
  40. //下单
  41. orders.put(KeyUtil.genUniqueKey(), productId);
  42. //减库存
  43. stockNum = stockNum - 1;
  44. try {
  45. Thread.sleep(100);
  46. } catch (Exception e) {
  47. e.printStackTrace();
  48. }
  49. stock.put(productId, stockNum);
  50. }
  51. //解锁
  52. redisLock.unlock(productId, String.valueOf(time));
  53. }
  54.  
  55. @Override
  56. public String querySecKillProductInfo(String productId) {
  57. return queryMap(productId);
  58. }
  59. }

浅谈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. 阶段3 2.Spring_02.程序间耦合_6 工厂模式解耦

    使用类加载器去加载文件 定义getBean的方法 运行测试方法报错. 在工厂类里面打印输出BeanPath 删除dao的实现类 没有dao的实现类.再次运行程序.编译不报错.运行时报错 以上就是工厂模 ...

  2. Python字符和字符值(ASCII或Unicode码值)转换方法

    Python字符和字符值(ASCII或Unicode码值)转换方法 这篇文章主要介绍了Python字符和字符值(ASCII或Unicode码值)转换方法,即把字符串在ASCII值或者Unicode值之 ...

  3. opensuse终端命令行安装编码解码器

    1) 添加必需的软件源:zypper addrepo -f http://packman.inode.at/suse/openSUSE_Leap_15.1/ packmanzypper addrepo ...

  4. 2019.8中关村、OGeek(oppo)比赛

    中关村writeup https://mp.weixin.qq.com/s?__biz=MzU3MzczNDg1OQ==&mid=2247484106&idx=1&sn=62a ...

  5. 模板中用url_for的好处

    from flask import Flask,render_template app = Flask(__name__) @app.route('/') def index(): return re ...

  6. spring boot-9.对springMVC的支持

    1.thymeleaf spring boot 推荐的模板引擎是thymeleaf.spring boot 的自动配置已经默认配置好了themleaf,只要导入themleaf的Starter就可以了 ...

  7. Linux 下面根据端口号 查询 可执行程序的路劲的方法

    1. 安装上lsof 的包 2. 使用 lsof 命令查看相关进程 lsof -i: 效果为: 3. 根据/proc 的目录查看可执行目录的文件位置 ll /proc/procid # procid ...

  8. Android事件监听(二)——点击鼠标事件

    Button.ImageButton事件监听(setOnClickListener) 方法一:通过匿名内部类实现 代码如下: package com.note.demo2; import androi ...

  9. 洛谷 P2868 [USACO07DEC]观光奶牛Sightseeing Cows 题解

    题面 这道题是一道标准的01分数规划: 但是有一些细节可以优化: 不难想到要二分一个mid然后判定图上是否存在一个环S,该环是否满足∑i=1t(Fun[vi]−mid∗Tim[ei])>0 但是 ...

  10. 洛谷 P1879 玉米田Corn Fields 题解

    题面 一道思维难度不大的状态压缩,也并不卡常,但细节处理要格外注意: f[i][j]表示前i行最后一行状态是j的方案数 #include <bits/stdc++.h> #define p ...