浅谈redis分布式锁用法
使用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分布式锁用法的更多相关文章
- Redis分布式锁的原理和实现
前言 我们之前聊过redis的,对基础不了解的可以移步查看一下: 几分钟搞定redis存储session共享--设计实现:https://www.cnblogs.com/xiongze520/p/10 ...
- redis分布式锁和消息队列
最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令. 分布式锁 由于目前一些编程语言,如PHP ...
- Redis分布式锁的try-with-resources实现
Redis分布式锁的try-with-resources实现 一.简介 在当今这个时代,单体应用(standalone)已经很少了,java提供的synchronized已经不能满足需求,大家自然 而 ...
- 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁
首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...
- Redlock:Redis分布式锁最牛逼的实现
普通实现 说道Redis分布式锁大部分人都会想到:setnx+lua,或者知道set key value px milliseconds nx.后一种方式的核心实现命令如下: - 获取锁(unique ...
- $.ajax()方法详解 ajax之async属性 【原创】详细案例解剖——浅谈Redis缓存的常用5种方式(String,Hash,List,set,SetSorted )
$.ajax()方法详解 jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为Str ...
- 五分钟DBA:浅谈伪分布式数据库架构
[IT168 技术]12月25日消息,2010互联网行业技术研讨峰会今日在上海华东理工大学召开.本次峰会以“互联网行业应用最佳实践”为主题,定位于互联网架构设计.应用开发.应用运维管理,同时,峰会邀请 ...
- 面试官:你真的了解Redis分布式锁吗?
什么是分布式锁 说到Redis,我们第一想到的功能就是可以缓存数据,除此之外,Redis因为单进程.性能高的特点,它还经常被用于做分布式锁. 锁我们都知道,在程序中的作用就是同步工具,保证共享资源在同 ...
- Redis分布式锁升级版RedLock及SpringBoot实现
分布式锁概览 在多线程的环境下,为了保证一个代码块在同一时间只能由一个线程访问,Java中我们一般可以使用synchronized语法和ReetrantLock去保证,这实际上是本地锁的方式.但是现在 ...
随机推荐
- 阶段3 2.Spring_02.程序间耦合_6 工厂模式解耦
使用类加载器去加载文件 定义getBean的方法 运行测试方法报错. 在工厂类里面打印输出BeanPath 删除dao的实现类 没有dao的实现类.再次运行程序.编译不报错.运行时报错 以上就是工厂模 ...
- Python字符和字符值(ASCII或Unicode码值)转换方法
Python字符和字符值(ASCII或Unicode码值)转换方法 这篇文章主要介绍了Python字符和字符值(ASCII或Unicode码值)转换方法,即把字符串在ASCII值或者Unicode值之 ...
- opensuse终端命令行安装编码解码器
1) 添加必需的软件源:zypper addrepo -f http://packman.inode.at/suse/openSUSE_Leap_15.1/ packmanzypper addrepo ...
- 2019.8中关村、OGeek(oppo)比赛
中关村writeup https://mp.weixin.qq.com/s?__biz=MzU3MzczNDg1OQ==&mid=2247484106&idx=1&sn=62a ...
- 模板中用url_for的好处
from flask import Flask,render_template app = Flask(__name__) @app.route('/') def index(): return re ...
- spring boot-9.对springMVC的支持
1.thymeleaf spring boot 推荐的模板引擎是thymeleaf.spring boot 的自动配置已经默认配置好了themleaf,只要导入themleaf的Starter就可以了 ...
- Linux 下面根据端口号 查询 可执行程序的路劲的方法
1. 安装上lsof 的包 2. 使用 lsof 命令查看相关进程 lsof -i: 效果为: 3. 根据/proc 的目录查看可执行目录的文件位置 ll /proc/procid # procid ...
- Android事件监听(二)——点击鼠标事件
Button.ImageButton事件监听(setOnClickListener) 方法一:通过匿名内部类实现 代码如下: package com.note.demo2; import androi ...
- 洛谷 P2868 [USACO07DEC]观光奶牛Sightseeing Cows 题解
题面 这道题是一道标准的01分数规划: 但是有一些细节可以优化: 不难想到要二分一个mid然后判定图上是否存在一个环S,该环是否满足∑i=1t(Fun[vi]−mid∗Tim[ei])>0 但是 ...
- 洛谷 P1879 玉米田Corn Fields 题解
题面 一道思维难度不大的状态压缩,也并不卡常,但细节处理要格外注意: f[i][j]表示前i行最后一行状态是j的方案数 #include <bits/stdc++.h> #define p ...