Redis6
9.3)Redis的事务秒杀案例
9.3.1)解决计数器和人员记录的事务操作
秒杀主要包括两个操作:1)商品库存 - 1 2)秒杀成功的该用户加到秒杀成功者清单里
?9.3.2)不考虑并发的秒杀案例实现
新建工程 Seckill ,这是一个WEB工程
创建页面:index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
? ?pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>iPhone 13 Pro !!! 1元秒杀!!!
</h1>
?
<form id="msform" action="${pageContext.request.contextPath}/doseckill" enctype="application/x-www-form-urlencoded">
<%--固定商品id设置为0101--%>
<input type="hidden" id="prodid" name="prodid" value="0101">
<input type="button" ?id="miaosha_btn" name="seckill_btn" value="秒杀点我"/>
</form>
?
</body>
<script ?type="text/javascript" src="${pageContext.request.contextPath}/script/jquery/jquery-3.1.0.js"></script>
<script ?type="text/javascript">
$(function(){
$("#miaosha_btn").click(function(){
var url=$("#msform").attr("action");
? ? $.post(url,$("#msform").serialize(),function(data){
? ? if(data=="false"){
? alert("抢光了" );
? $("#miaosha_btn").attr("disabled",true);
? }
} );
})
})
</script>
</html>
创建 SecKillServlet,页面按钮点击秒杀调用doPost()方法
public class SecKillServlet extends HttpServlet {
? ?private static final long serialVersionUID = 1L;
?
? ?public SecKillServlet() {
? ? ? ?super();
? }
?
? ?@Override
? ?protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
? // 通过随机数生成用户id
? ? ? ?String userid = new Random().nextInt(50000) + "";
? ? ? ?// 接收调用的商品id
? ? ? ?String prodid = request.getParameter("prodid");
? ? ? ?// 调用秒杀方法
? ? ? ?boolean isSuccess = SecKill_redis.doSecKill(userid, prodid);
? ? ? ?// 根据秒杀的返回结果返回相应信息
? ? ? ?response.getWriter().print(isSuccess);
? }
}
创建 SecKill_redis.java,秒杀主方法,秒杀的全流程在这里开发
public class SecKill_redis {
?
? ?public static void main(String[] args) {
? ? ? ?Jedis jedis = new Jedis("82.157.183.197", 11079);
? ? ? ?System.out.println(jedis.ping());
? ? ? ?jedis.close();
? }
?
? ?//秒杀主方法--全过程
? ?public static boolean doSecKill(String uid, String prodid) throws IOException {
? ? ? ?//步骤1 根据入参用户ID-uid和商品ID-prodid 进行非空判断
? ? ? ?if (uid == null || prodid == null) {
? ? ? ? ? ?return false;
? ? ? }
?
? ? ? ?//步骤2 连接redis
? ? ? ?Jedis jedis = new Jedis("127.0.0.1", 11079);
?
? ? ? ?//步骤3 拼接key
? ? ? ?// 3.1 库存key
? ? ? ?String kcKey = "sk:" + prodid + ":qt";
? ? ? ?// 3.2 秒杀成功的用户key
? ? ? ?String userKey = "sk:" + prodid + ":user";
?
? ? ? ?// 步骤4 获取库存,如果库存null,秒杀还没有开始
? ? ? ?String kc = jedis.get(kcKey);
? ? ? ?if (kc == null) {
? ? ? ? ? ?System.out.println("秒杀还没有开始,请等待");
? ? ? ? ? ?jedis.close();
? ? ? ? ? ?return false;
? ? ? }
?
? ? ? ?// 步骤5 判断用户是否重复秒杀操作
? ? ? ?// 判断set集合中的用户信息,因为不能存在重复的用户【不能重复秒杀】所以使用Set存储用户信息
? ? ? ?if (jedis.sismember(userKey, uid)) {
? ? ? ? ? ?System.out.println("已经秒杀成功了,不能重复秒杀");
? ? ? ? ? ?jedis.close();
? ? ? ? ? ?return false;
? ? ? }
?
? ? ? ?// 步骤6 判断如果商品数量,库存数量小于1,秒杀结束
? ? ? ?if (Integer.parseInt(kc) <= 0) {
? ? ? ? ? ?System.out.println("秒杀已经结束了");
? ? ? ? ? ?jedis.close();
? ? ? ? ? ?return false;
? ? ? }
?
? ? ? ?// 步骤7 秒杀的过程
? ? ? ?//7.1 库存-1
? ? ? ?jedis.decr(kcKey);
? ? ? ?//7.2 把秒杀成功用户添加清单里面
? ? ? ?jedis.sadd(userKey, uid);
?
? ? ? ?System.out.println("秒杀成功了..");
? ? ? ?jedis.close();
? ? ? ?return true;
? }
}
测试:启动Tomcat工程
浏览器访问:http://localhost:8080/Seckill/
点击 “秒杀按钮” ,此时还未向 Redis 中添加 商品信息,效果如下图:
?向Redis中加入商品信息,命令如下:【添加了5个商品】
127.0.0.1:11079> flushdb
OK
127.0.0.1:11079> keys *
(empty array)
127.0.0.1:11079> set sk:0101:qt 5
OK
127.0.0.1:11079> keys *
1) "sk:0101:qt"
刷新页面后再次点击秒杀按钮”,效果如下图:
?弹框不再弹出,且后台提示 —— 秒杀成功了..
在Redis中查看相关商品和用户信息:
127.0.0.1:11079> get sk:0101:qt
"4"
127.0.0.1:11079> smembers sk:0101:user
1) "452"
发现商品数量已减少1,用户列表新增了秒杀成功的用户
再次点击秒杀按钮”,直到第六次,效果如下图:
?弹框再次弹出,且后台提示 —— 秒杀已经结束了
在Redis中查看相关商品和用户信息:
127.0.0.1:11079> get sk:0101:qt
"0"
127.0.0.1:11079> smembers sk:0101:user
1) "452"
2) "16928"
3) "27602"
4) "41023"
5) "41347"
发现商品信息已经为0,同时用户列表中已经有了5个秒杀成功的用户
并发测试:
在Linux系统中安装:
yum install httpd-tools
通过ab进行测试
在根目录新建 postfile 文件,内容如下:
prodid=0101&
在根目录执行下列命令,执行并发测试
ab -n 1000 -c 100 -p ~/postfile -T application/x-www-form-urlencoded http://172.19.83.237:8080/Seckill/doseckill
【1000个请求、100个并发,调用172.19.83.237(个人主机)上的秒杀方法】
输出:
存在问题:?
|