首页 > 数据库 >Redis事务-秒杀并发模拟

Redis事务-秒杀并发模拟

时间:2023-06-04 17:11:49浏览次数:35  
标签:return String Redis redis 并发模拟 秒杀 import redisTemplate

使用工具ab模拟测试:yum install httpd-tools

ab --help:使用信息

ab -n 1000 -c 100 http://localhost8080/SecKill :一个1000请求中有100个并发操作

vim postfile 模拟表单提交参数,以&符号结尾;存放当前目录,内容:prodid=0101&

ab -n 1000 -c 100 -p ~/postfile -T application/x-www-form-urlencoded http://172.22.3.22:8080/seckill/getThing

存在问题:

并发导致库存出现负值

连接超时问题

一、连接超时问题

连接池:节省每次连接redis服务带来的消耗,把连接好的实例反复使用,通过参数管理连接的行为

二、超卖问题

利用乐观锁淘汰用户,解决超卖问题。


package com.atguigu.seckill.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.List;
import java.util.Random;

@RestController
@RequestMapping("/seckill")
public class SecKController {
@Autowired
private RedisTemplate redisTemplate;

@GetMapping
public String test(){
redisTemplate.opsForValue().set("name", "lucky");
String name = (String)redisTemplate.opsForValue().get("name");
System.out.println(name);
return name;
}

//秒杀过程
@PostMapping("/getThing")
public boolean getThing(@RequestParam String prodid){

redisTemplate.setEnableTransactionSupport(true);
String uid = new Random().nextInt(50000) +"" ;
//1 uid和prodid非空判断
if(uid == null || prodid == null){
return false;
}
//2、拼接key
//2.1 秒杀库存key
String kcKey = "sk:" + prodid +":qt";
//2.2 秒杀成功用户key
String userKey = "sk:" + prodid + ":user";


//6 秒杀过程
SessionCallback<Object> callback = new SessionCallback<Object>() {
@Override
public Object execute(RedisOperations operations) throws DataAccessException {
// 监视库存
redisTemplate.watch(kcKey);
//3 获取库存,如果库存null,秒杀没有开始
Object kc = redisTemplate.opsForValue().get(kcKey);
if(kc == null){
System.out.println("秒杀还没开始,请等待");
return false;
}
String kcnum = String.valueOf(kc);

//4 判断用户是否重复秒杀操作
if(redisTemplate.opsForSet().isMember(userKey, uid)){
System.out.println("已经秒杀成功,不能重复秒杀");
return false;
}
//5 判断如果商品数量<=0,秒杀结束
if(Integer.parseInt(kcnum)<=0){
System.out.println("秒杀已结束");
return false;
}

// 开启事务
operations.multi();
operations.opsForValue().decrement(kcKey);
operations.opsForSet().add(userKey, uid);
// 执行事务
List<Object> results= operations.exec();
if(results == null || results.size() == 0){
return false;
}
return true;
}
};

boolean results = (boolean)redisTemplate.execute(callback);
if(results == false){
System.out.println("秒杀失败.......");
return results;
}

System.out.println("秒杀成功了");
return results;
}

}
 

三、库存遗留问题

乐观锁造成库存遗留问题:比如2000个人购买500件产品,恰好一个人买了把版本号从1.0修改为1.1,剩余1999个人都无法购买,导致还剩余499件商品库存遗留。

解决:Lua脚本语言,将复杂或者多步的redis操作,写为一个脚本,一次提交给redis执行,减少反复连接redis次数,提升性能。

Lua脚本是类似redis事务,有一定的原子性,不会被其它命令插队,可以完成一些redis事务的操作。

利用lua脚本淘汰用户,解决超卖问题。实际上redis利用其单线程特性,用任务队列的方式解决多任务并发问题

 

标签:return,String,Redis,redis,并发模拟,秒杀,import,redisTemplate
From: https://www.cnblogs.com/fxzm/p/17455916.html

相关文章

  • Docker安装Java, Apache, Redis, Tomcat, Postgresql, SSH
    [color=red]centos安装Supervisor[/color][url]http://www.alphadevx.com/a/455-Installing-Supervisor-and-Superlance-on-CentOS[/url]网络设定[b][color=darkblue]#创建网络brctladdbrbr0iplinksetdevbr0upipaddradd192.168.2.1/24devbr0#创建容器#......
  • 秒杀案例
    packagecom.atguigu.seckill.controller;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bin......
  • 踩坑|以为是Redis缓存没想到却是Spring事务!
    前言  最近碰到了一个Bug,折腾了我好几天。并且这个Bug不是必现的,出现的概率比较低。一开始我以为是旧数据的问题,就让测试重新生成了一下数据,重新测试。由于后面几轮测试均未出现,我也就没太在意。  可惜好景不长,测试反馈上次的问题又出现了。于是我立马着手排查,根据日志的表......
  • Redis(二) -- 练习
    模拟手机验证码需求:使用redis模拟手机验证码发送,验证码有效期60s,验证验证码输入不能超过3次,超过3次今天就没机会了//验证手机号/***判断字符串是否符合手机号码格式*移动号段:134135136137138139147148150151152157158159165172178182183184187......
  • Redis
    关系型数据库(RMDBS)如果数据库中表与表之间存在某种关联的内在关系,我们就称这种数据库为关系型数据库。比如:Mysql/MariaDB、postgreSQL、Oracle、SQLServer、DB2、Access、SQLlite3特点:全部使用SQL(结构化查询语言)进行数据库操作。都存在主外键关系等关系特征。大部分都支持......
  • 2023-06-03:redis中pipeline有什么好处,为什么要用 pipeline?
    2023-06-03:redis中pipeline有什么好处,为什么要用pipeline?答案2023-06-03:Redis客户端执行一条命令通常包括以下四个阶段:1.发送命令:客户端将要执行的命令发送到Redis服务器。2.命令排队:Redis服务器将收到的命令放入队列中,按照先进先出(FIFO)的原则等待执行。3.命令执行:当Redis服务器轮......
  • 2023-06-03:redis中pipeline有什么好处,为什么要用 pipeline?
    2023-06-03:redis中pipeline有什么好处,为什么要用pipeline?答案2023-06-03:Redis客户端执行一条命令通常包括以下四个阶段:1.发送命令:客户端将要执行的命令发送到Redis服务器。2.命令排队:Redis服务器将收到的命令放入队列中,按照先进先出(FIFO)的原则等待执行。3.命令执行:当Redis服......
  • redis设计学习
    redis数据类型redis自定义字符串(SDS)redis自定义一种字符串SDS(SimpleDynamicString),该字符串数据结构大概定义了字符编码,char[]数组存储字节,达到了我们存储字符串和二进制数据的需求,也实现了我们存储不同编码的字符串和二进制图片等数据。区别于C语言中的String,这种字符串起......
  • redis主从数据同步的原理
    redis主从数据同步的原理数据同步原理主从第一次同步是全量同步,但是如果slave重启后同步,则执行增量同步。第一阶段slave和master建立第一次同步的时候,需要执行replicaof命令,并且指定了master的ip和端口,slave和master连接一旦建立成功,slave就会向master发出请求来数据同步,然后......
  • 大件货运系统源码,技术架构:spring boot、mybatis、redis、vue、element-ui
    网络货运平台源码网络货运平台的功能网络货运是指利用互联网平台,通过物流配送的方式进行商品销售和物流运输的一种新型商业模式。这种模式将传统的货运模式与互联网技术相结合,通过网络平台进行交易、物流配送和结算等一系列流程,从而实现货物的快速、高效、便捷地运输。技术架构:spr......