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 废话不多说,首先分享一个业务场景-抢购.一个典型的高并发问题,所需的最关键字段就是库存,在高并发的情况下每次 ...
随机推荐
- .apk等常用文件下载出现如果应下载文件,请添加 iis MIME 映射。
在下载.apk文件时出现错误. HTTP 错误 404.3 - Not Found 由于扩展配置问题而无法提供您请求的页面.如果该页面是脚本,请添加处理程序.如果应下载文件,请添加 MIME 映射. ...
- vb6.0的安装
vb6.0古老的编程软件
- Spring,Struts2,MyBatis,Activiti,Maven,H2,Tomcat集成(一)——Maven,Tomcat,Spring集成
1. 创建Maven Web工程 (1) 磁盘上创建Maven工程所需要的文件夹结构如下: (2) 在与src同级目录中创建pom.xml文件: <project xm ...
- 用rewrite把旧域名直接跳转到新域名的nginx配置
用rewrite把旧域名直接跳转到新域名的nginx配置 把下面代码保存到daziran.com.conf 放在nginx配置目录下 /etc/nginx/conf.d/ #把旧域名zdz8207直接 ...
- Linux(CentOS)下同时启动两个tomcat
问题背景:在配置nginx时,配置了两个tomcat,tomcat01和tomcat02,改了tomcat02中server.xml的端口,可是还是启动不起来. 解决方法: 一.编辑环境变量: 1 v ...
- SNMP学习笔记之SNMP TRAP简介、流程以及使用Python实现接受Trap信息
0x00 SNMP TRAP简介 SNMP(Simple Network Management Protocol) trap是一种很有用,但是也容易让人难以理解的协议. 虽然名字叫做简单网络管理协议, ...
- SNMP学习笔记之SNMP 原理与实战详解
原文地址:http://freeloda.blog.51cto.com/2033581/1306743 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法 ...
- Linux 虚拟机安装vmware tools
Linux Vmware tools安装步骤 1 在 vSphere Client 清单中,右键单击虚拟机,然后选择电源 > 开启. 2 单击控制台选项卡以确定客户机操作系统启动成功,并在需 ...
- 20145127 《Java程序设计》第四次实验报告
在本周,我们进行了Andirod部分的学习,这一次实验是使用Andirod Studio来运行简单的Andirod小程序,并在自己的手机虚拟机上显示自己的学号,为了达到这一效果,我在Andirod S ...
- python的回收机制
1,我们为什么要启用变量 因为我也不确定用户扔给我的数据是什么,有些同学在写程序的时候就已经将变量限定死了,我就说你这样不好,你只想测试一次吗,如果你想确保你的程序万无一失,通俗点说的话,就是“抗揍” ...