Redis分布式锁实现简单秒杀功能
这版秒杀只是解决瞬间访问过高服务器压力过大,请求速度变慢,大大消耗服务器性能的问题。
主要就是在高并发秒杀的场景下,很多人访问时并没有拿到锁,所以直接跳过了。这样就处理了多线程并发问题的同时也保证了服务器的性能的稳定。
接下来我们使用redis的分布式锁来进行枷锁处理:
我们可以在进入下单的方法后将核心的方法加锁,然后离开后进行解锁
主要三步:
加锁
核心方法
解锁
首页分布式加锁解锁工具类:
@Component
public class RedisLock {
private static Logger logger = LoggerFactory.getLogger(RedisLock.class); @Autowired
private StringRedisTemplate redisTemplate; /**
* 加锁
* @param key
* @param value 当前事件+超时事件
* @return
*/
public boolean lock(String key,String value){
//加锁成功
if (redisTemplate.opsForValue().setIfAbsent(key,value)){
return true;
}
//假如currentValue=A先占用了锁 其他两个线程的value都是B,保证其中一个线程拿到锁
String currentValue = redisTemplate.opsForValue().get(key);
//锁过期 防止出现死锁
if (!StringUtils.isEmpty(currentValue) &&
Long.parseLong(currentValue) < System.currentTimeMillis()){
//获取上一步锁的时间
String oldValue = redisTemplate.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 = redisTemplate.opsForValue().get(key);
if (!StringUtils.isEmpty(currentValue) &&
currentValue.equals(value)){
redisTemplate.opsForValue().getOperations().delete(key);
}
}catch (Exception e){
logger.error("【redis分布式锁】 解锁异常,{}",e);
}
}
}
具体使用的逻辑代码功能:
@Service
public class SecKillService {
private static Logger logger = LoggerFactory.getLogger(SecKillService.class);
/** 超时时间 */
private static final int TIMEOUT = 10000; @Autowired
private RedisLock redisLock;
@Autowired
private RedisClient redisClient;
@Autowired
private RestTemplate restTemplate; /**
* @Description: 秒杀商品接口
* @param weddingExpoAppoint
* @return JsonObject
* @exception
* @author mazhq
* @date 2018/11/18 13:46
*/
private JsonObject seckillProduct(long productId) {
long time = System.currentTimeMillis() + TIMEOUT;
String stockKey = RedisKeysManager.getWeddingExpoSeckillStockKey(productId);
//加锁
String lockKey = "weddingExpo:seckill:"+productId;
if (!redisLock.lock(lockKey,String.valueOf(time))){
return BaseCode.retCode(100, "没抢到,换个姿势再来一遍");
} String stockNumStr = redisClient.getStr(stockKey);
int stockNum = 0;
if(StringUtils.isNotBlank(stockNumStr)){
stockNum = Integer.valueOf(stockNumStr);
}
JsonObject respJson = BaseCode.retCode(ResultCode.failure);
if (stockNum == 0) {
//库存不足
return BaseCode.retCode(100, "商品已经被抢光了,请留意下次活动");
} else { try {
String resp = doseckill(productId);
if(null != resp){
respJson = new JsonObject(resp);
if(respJson.getInteger("retcode") == 0){
redisClient.increment(stockKey, -1);
}
Thread.sleep(100);
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
//解锁
redisLock.unlock(lockKey, String.valueOf(time));
return respJson;
} }
主要功能描述就是:
秒杀商品时候先加锁,如果没有获取到锁就释放请求。
加锁后先进行库存判断如果不足释放请求。
进行秒杀下单流程,如果成功库存做减一操作。
最后释放分布式锁。
这样简单的分布式锁处理秒杀功能的方法就搞定了。这种只是处理高并发下多个请求如果有人在秒杀后面的直接不需排队直接释放请求,解放服务器压力(处理流程时间较短,高并发下没有排序要求)。
如果要根据请求时间进行排序,这个方式还需借助队列处理。
Redis分布式锁实现简单秒杀功能的更多相关文章
- 单实例redis分布式锁的简单实现
redis分布式锁的基本功能包括, 同一刻只能有一个人占有锁, 当锁被其他人占用时, 获取者可以等待他人释放锁, 此外锁本身必须能超时自动释放. 直接上java代码, 如下: package com. ...
- redis 分布式锁的简单使用
RedisLock--让 Redis 分布式锁变得简单 目录 1. 项目介绍 2. 快速使用 2.1 引入 maven 坐标 2.2 注册 RedisLock 2.3 使用 3. 参与贡献 4. 联系 ...
- 利用redis分布式锁的功能来实现定时器的分布式
文章来源于我的 iteye blog http://ak478288.iteye.com/blog/1898190 以前为部门内部开发过一个定时器程序,这个定时器很简单,就是配置quartz,来实现定 ...
- .NetCore使用Redis,StackExchange.Redis队列,发布与订阅,分布式锁的简单使用
环境:之前一直是使用serverStack.Redis的客服端,今天来使用一下StackExchange.Redis(个人感觉更加的人性化一些,也是免费的,性能也不会差太多),版本为StackExch ...
- Redis分布式锁----乐观锁的实现,以秒杀系统为例
本文使用redis来实现乐观锁,并以秒杀系统为实例来讲解整个过程. 乐观锁 大多数是基于数据版本(version)的记录机制实现的.即为数据增加一个版本标识,在基于数据库表的版本解决方案中, ...
- springboot项目:Redis分布式锁的使用(模拟秒杀系统)
模拟秒杀系统: 第一步:编写Service package com.payease.service; /** * liuxiaoming * 2017-12-14 */ public interfac ...
- 自己写了个简单的redis分布式锁【我】
自己写了个简单的redis分布式锁 [注意:此锁需要在每次使用前都创建对象,也就是要在线程内每次都创建对象后使用] package redis; import java.util.Collection ...
- Redis分布式锁的实现
前段时间,我在的项目组准备做一个类似美团外卖的拼手气红包[第X个领取的人红包最大],基本功能实现后,就要考虑这一操作在短时间内多个用户争抢同一资源的并发问题了,类似于很多应用如淘宝.京东的秒杀活动场景 ...
- Redis分布式锁解决抢购问题
转:https://segmentfault.com/a/1190000011421467 废话不多说,首先分享一个业务场景-抢购.一个典型的高并发问题,所需的最关键字段就是库存,在高并发的情况下每次 ...
随机推荐
- mysql普通查询日志
- mongodb部署
windows版本 http://dl.mongodb.org/dl/win32/x86_64 安装教程 https://docs.mongodb.org/manual/tutorial/instal ...
- mysql性能优化1
当我们去设计数据库表结构,对操作数据库时(尤其是查表时的SQL语句),我们都需要注意数据操作的性能.这里,我们不会讲过多的SQL语句的优化,而只是针对MySQL这一Web应用最多的数据库.希望下面的这 ...
- Linux基础命令---mknod
mknod 创建块设备或者字符设备文件.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. 1.语法 mknod [选项] ...
- python3.4学习笔记(六) 常用快捷键使用技巧,持续更新
python3.4学习笔记(六) 常用快捷键使用技巧,持续更新 安装IDLE后鼠标右键点击*.py 文件,可以看到Edit with IDLE 选择这个可以直接打开编辑器.IDLE默认不能显示行号,使 ...
- DNS正反向区域解析(二)
域名查询工具 Nslookup命令 >server 202.106.0.20 #指定DNS服务器 >set q=A #指定要查询的类型(A,PTR,MX,CNAME,NS) >www ...
- 20165310 Java实验五《网络编程与安全》
20165310 Java实验五<网络编程与安全> 任务一 题目:①编写MyBC.java实现中缀表达式转后缀表达式的功能:②编写MyDC.java实现从上面功能中获取的表达式中实现后缀表 ...
- 2018-2019-1 20189218《Linux内核原理与分析》第六周作业
向menuOS中增加命令 修改menu目录下的test.c文件,增加自己的函数定义,并在修改main()函数,按照前面的menuconfig的写法写好自己的menuconfig. 我选择的是acces ...
- Python3基础 str while+iter+next 字符串的遍历
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- Hexo 搭建 Blog 精简笔记
安装Hexo npm install -g hexo-cli Mac 用户 您在编译时可能会遇到问题,请先到 App Store 安装 Xcode,Xcode 完成后,启动并进入 Preference ...