码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 五.Redis_事务秒杀案例


    5.1 解决计数器和人员记录的事务操作

    5.2 Redis 事务 — 秒杀并发模拟

    使用工具 ab 模拟测试:

    CentOS6 默认安装

    CentOS7 需要手动安装

    通过 ab 测试

    im postfile 模拟表单提交参数, 以 & 符号结尾,存放当前目录。

    内容:prodid=0101&

    执行:ab -n 2000 -c 200 -k -p ~/postfile -T application/x-www-form-urlencoded

    访问:http://192.168.2.115:8081/Seckill/doseckill

    超卖

    5.3 超卖问题

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

    主要代码:

    1. 1. public class SecKill_redis {
    2. 2.
    3. 3. public static void main(String[] args) {
    4. 4. Jedis jedis =new Jedis("192.168.44.168",6379);
    5. 5. System.out.println(jedis.ping());
    6. 6. jedis.close();
    7. 7. }
    8. 8.
    9. 9. //秒杀过程
    10. 10. public static boolean doSecKill(String uid,String prodid) throws IOException {
    11. 11. //1 uid和prodid非空判断
    12. 12. if(uid == null || prodid == null) {
    13. 13. return false;
    14. 14. }
    15. 15.
    16. 16. //2 连接redis
    17. 17. //Jedis jedis = new Jedis("192.168.44.168",6379);
    18. 18. //通过连接池得到jedis对象
    19. 19. JedisPool jedisPoolInstance = JedisPoolUtil.getJedisPoolInstance();
    20. 20. Jedis jedis = jedisPoolInstance.getResource();
    21. 21.
    22. 22. //3 拼接key
    23. 23. // 3.1 库存key
    24. 24. String kcKey = "sk:"+prodid+":qt";
    25. 25. // 3.2 秒杀成功用户key
    26. 26. String userKey = "sk:"+prodid+":user";
    27. 27.
    28. 28. //监视库存
    29. 29. jedis.watch(kcKey);
    30. 30.
    31. 31. //4 获取库存,如果库存null,秒杀还没有开始
    32. 32. String kc = jedis.get(kcKey);
    33. 33. if(kc == null) {
    34. 34. System.out.println("秒杀还没有开始,请等待");
    35. 35. jedis.close();
    36. 36. return false;
    37. 37. }
    38. 38.
    39. 39. // 5 判断用户是否重复秒杀操作
    40. 40. if(jedis.sismember(userKey, uid)) {
    41. 41. System.out.println("已经秒杀成功了,不能重复秒杀");
    42. 42. jedis.close();
    43. 43. return false;
    44. 44. }
    45. 45.
    46. 46. //6 判断如果商品数量,库存数量小于1,秒杀结束
    47. 47. if(Integer.parseInt(kc)<=0) {
    48. 48. System.out.println("秒杀已经结束了");
    49. 49. jedis.close();
    50. 50. return false;
    51. 51. }
    52. 52.
    53. 53. //7 秒杀过程
    54. 54. //使用事务
    55. 55. Transaction multi = jedis.multi();
    56. 56.
    57. 57. //组队操作
    58. 58. multi.decr(kcKey);
    59. 59. multi.sadd(userKey,uid);
    60. 60.
    61. 61. //执行
    62. 62. List results = multi.exec();
    63. 63.
    64. 64. if(results == null || results.size()==0) {
    65. 65. System.out.println("秒杀失败了....");
    66. 66. jedis.close();
    67. 67. return false;
    68. 68. }
    69. 69.
    70. 70. //7.1 库存-1
    71. 71. //jedis.decr(kcKey);
    72. 72. //7.2 把秒杀成功用户添加清单里面
    73. 73. //jedis.sadd(userKey,uid);
    74. 74.
    75. 75. System.out.println("秒杀成功了..");
    76. 76. jedis.close();
    77. 77. return true;
    78. 78. }
    79. 79. }
    80. 5.4 继续增加并发测试

      连接有限制

      增加 - r 参数,-r Don’t exit on socket receive errors。

      已经秒光,可是还有库存

      已经秒光,可是还有库存。原因:乐观锁导致很多请求都失败。先点的没秒到,后点的可能秒到了。

      连接超时,通过连接池解决

      节省每次连接 redis 服务带来的消耗,把连接好的实例反复利用。通过参数管理连接的行为,代码见项目中:

      连接池参数:

      MaxTotal:控制一个 pool 可分配多少个 jedis 实例,通过 pool.getResource () 来获取;如果赋值为 - 1,则表示不限制;如果 pool 已经分配了 MaxTotal 个 jedis 实例,则此时 pool 的状态为 exhausted。

      maxIdle:控制一个 pool 最多有多少个状态为 idle (空闲) 的 jedis 实例;

      MaxWaitMillis:表示当 borrow 一个 jedis 实例时,最大的等待毫秒数,如果超过等待时间,则直接抛 JedisConnectionException;

      testOnBorrow:获得一个 jedis 实例的时候是否检查连接可用性(ping ());如果为 true,则得到的 jedis 实例均是可用的。

      5.5 解决库存遗留问题

      LUA 脚本在 Redis 中的优势

      • 将复杂的或者多步的 redis 操作,写为一个脚本,一次提交给 redis 执行,减少反复连接 redis 的次数,提升性能。
      • LUA 脚本是类似 redis 事务,有一定的原子性,不会被其他命令插队,可以完成一些 redis 事务性的操作。
      • 但是注意 redis 的 lua 脚本功能,只有在 Redis 2.6 以上的版本才可以使用。
      • 利用 lua 脚本淘汰用户,解决超卖问题,redis 2.6 版本以后,通过 lua 脚本解决争抢问题,实际上是 redis 利用其单线程的特性,用任务队列的方式解决多任务并发问题。

    81. 相关阅读:
      【解决方案】数据随机生成脚本
      新手入门:LoadRunner调用Analysis组件的相关技术点及知识总结
      热门Java开发工具IDEA入门指南——从Eclipse迁移到IntelliJ IDEA(三)
      C++ 矩形图像旋转后的宽高计算方法
      从win11切换到ubuntu20的第1天
      每日一学—JavaScript Math对象
      CentOS7安装MYSQL8.X的教程详解
      力扣(LeetCode)97. 交错字符串(C++)
      Spring 5高级编程,投入Spring的怀抱
      IS-IS
    82. 原文地址:https://blog.csdn.net/qq_42428269/article/details/126207910
      • 最新文章
      • 攻防演习之三天拿下官网站群
        数据安全治理学习——前期安全规划和安全管理体系建设
        企业安全 | 企业内一次钓鱼演练准备过程
        内网渗透测试 | Kerberos协议及其部分攻击手法
        0day的产生 | 不懂代码的"代码审计"
        安装scrcpy-client模块av模块异常,环境问题解决方案
        leetcode hot100【LeetCode 279. 完全平方数】java实现
        OpenWrt下安装Mosquitto
        AnatoMask论文汇总
        【AI日记】24.11.01 LangChain、openai api和github copilot
      • 热门文章
      • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
        奉劝各位学弟学妹们,该打造你的技术影响力了!
        五年了,我在 CSDN 的两个一百万。
        Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
        面试官都震惊,你这网络基础可以啊!
        你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
        心情不好的时候,用 Python 画棵樱花树送给自己吧
        通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
        13 万字 C 语言从入门到精通保姆级教程2021 年版
        10行代码集2000张美女图,Python爬虫120例,再上征途
      Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
      正则表达式工具 cron表达式工具 密码生成工具

      京公网安备 11010502049817号