qidao123.com技术社区-IT企服评测·应用市场

标题: 十. Redis 事务和 “锁机制”——> 并发秒杀处理的详细阐明 [打印本页]

作者: 傲渊山岳    时间: 2025-2-12 17:31
标题: 十. Redis 事务和 “锁机制”——> 并发秒杀处理的详细阐明
十. Redis 事务和 “锁机制”——> 并发秒杀处理的详细阐明

@
目录

1.  Redis 的事务是什么?

2. Redis 事务三特性

队列中的命令(指令),在没有提交前都不会实际被执行。
事务执行过程中,如果有指令执行失败,其他的指令仍然会被执行,没有回滚
MySQL中的事务是支持回滚的,而 Redis 中的事务是不支持回滚的。
3. Redis 关于事务相关指令 Multi、Exec、discard和 “watch &    unwatch”







Redis 事务指令示意图:

上图解读:
3.1 快速入门(演示 Redis 事务控制)

  1. 127.0.0.1:6379> multi
复制代码
  1. 127.0.0.1:6379(TX)> set k1 v1
  2. QUEUED
  3. 127.0.0.1:6379(TX)> set k2 v2
  4. QUEUED
  5. 127.0.0.1:6379(TX)> set k3 v3
  6. QUEUED
  7. 127.0.0.1:6379(TX)>
复制代码
  1. 127.0.0.1:6379(TX)> exec
复制代码

3.2 注意事项和细节

  1. 127.0.0.1:6379(TX)> discard
复制代码





  1. 127.0.0.1:6379> multi
  2. OK
  3. 127.0.0.1:6379(TX)> set k1 "v1"
  4. QUEUED
  5. 127.0.0.1:6379(TX)> incr k1
  6. QUEUED
  7. 127.0.0.1:6379(TX)> set k2 "v2"
  8. QUEUED
  9. 127.0.0.1:6379(TX)> exec
  10. 1) OK
  11. 2) (error) ERR value is not an integer or out of range
  12. 3) OK
  13. 127.0.0.1:6379>
复制代码

4. Redis 事务冲突及解决方案(悲观锁,乐观锁) watch &    unwatch

我们先来看一个经典的抢票 问题。

上述解图:
一共只有10张票,但是并发开始,三个用户(三个请求),买 6 张,买 5 张,买 1 张票的。同时进入购票系统,并发同时候进入判定,都显示还剩10张票(还没有减),最后执行减票,超卖了 2张票。
4.1 “悲观锁” 解决


上图解图:
4.2 “乐观锁” 解决


上图解读:
4.3 watch &    unwatch


演示实操:



  1. # A 连接
  2. 127.0.0.1:6379> watch k1
  3. OK
  4. 127.0.0.1:6379> multi
  5. OK
  6. 127.0.0.1:6379(TX)> incrby k1 1
  7. QUEUED
  8. 127.0.0.1:6379(TX)> exec
  9. 1) (integer) 100
  10. 127.0.0.1:6379> get k1
  11. "100"
复制代码
  1. # B 连接
  2. 127.0.0.1:6379> watch k1
  3. OK
  4. 127.0.0.1:6379> multi
  5. OK
  6. 127.0.0.1:6379(TX)> incrby k1 100
  7. QUEUED
  8. 127.0.0.1:6379(TX)> exec
  9. (nil)
  10. 127.0.0.1:6379> get k1
  11. "100"
  12. 127.0.0.1:6379>
复制代码
unwatch:

5. 案例演示:火车票-抢票(解决超卖,库存遗留)问题

5.1 案例思绪分析:

这里我们使用 WEB 项目来演示


思绪分析:

5.2 完成基本购票流程,暂不考虑事务和并发问题














index.jsp 代码编写
  1. <%--
  2.   Created by IntelliJ IDEA.
  3.   User: 韩顺平
  4.   Version: 1.0
  5. --%>
  6. <%@ page language="java" contentType="text/html; charset=UTF-8"
  7.          pageEncoding="UTF-8" %>
  8. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  9. <html>
  10. <head>
  11.   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  12.   <title>Insert title here</title>
  13.   <base href="<%=request.getContextPath() + "/"%>">
  14. </head>
  15. <body>
  16. <h1>北京-成都 火车票 ! 秒杀!
  17. </h1>
  18. <form id="secKillform" action="secKillServlet" enctype="application/x-www-form-urlencoded">
  19.   <input type="hidden" id="ticketNo" name="ticketNo" value="bj_cd">
  20.   <input type="button" id="seckillBtn" name="seckillBtn" value="秒杀火车票【北京-成都】"/>
  21. </form>
  22. </body>
  23. </html>
复制代码
  1. package com.rainbowsea.seckill.redis;
  2. import org.junit.Test;
  3. import redis.clients.jedis.Jedis;
  4. /**
  5. * 秒杀类
  6. */
  7. public class SecKillRedis {
  8.     /**
  9.      * 编写一个测试方法-看看是否能够连通指定的 Redis
  10.      */
  11.     @Test
  12.     public void testRedis() {
  13.         Jedis jedis = new Jedis("192.168.76.146", 6379);
  14.         jedis.auth("rainbowsea");  // 设置了密码,需要进行一个验证
  15.         System.out.println(jedis.ping());
  16.         jedis.close(); // 关闭连接
  17.     }
  18. }
复制代码
<blockquote>
关于更多对应:Java程序连接 Redis 的内容,大家可以移步至:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4