zoukankan      html  css  js  c++  java
  • 秒杀系统,库存优化

    直接上代码

     1 public class RedisShop {
     2 
     3     private final static String PRODUCT_STOCK_KEY = "productStockKey";
     4     private static ConcurrentHashMap<Long, Boolean> productSoldOutMap = new ConcurrentHashMap<>();
     5     private static ConcurrentHashMap<Long, Boolean> getProductSoldOutMap() {
     6         return productSoldOutMap;
     7     }
     8 
     9     @Autowired
    10     private ProductService productService;
    11     @Autowired
    12     private StringRedisTemplate stringRedisTemplate;
    13     @Autowired
    14     private Zookeeper zookeeper;
    15 
    16     /**
    17      * 将数据添加至redis缓存
    18      */
    19     public void init() {
    20 
    21         List<PoductInfo> products = productService.getProductList();
    22 
    23         for (PoductInfo productInfo : products) {
    24 
    25             stringRedisTemplate.opsForValue().set(PRODUCT_STOCK_KEY + productInfo.getProductId, productInfo.getStock());
    26         }
    27 
    28     }
    29 
    30     public String soleProduct(Long productId) {
    31 
    32         //优化3:创建一个ConcurrentHashMap集合(Jvm线程同步),不等于空==已售完
    33         if (productSoldOutMap.get(productId) != null) {
    34 
    35             return "商品已售完";
    36         }
    37 
    38         //优化2:将redis缓存中的数据-1,并返回减1后的值
    39         Long stock = stringRedisTemplate.opsForValue().decrement(PRODUCT_STOCK_KEY + productId);
    40         if (stock < 0) {
    41 
    42             //优化3:库存不足时,向ConcurrentHashMap添加值
    43             getProductSoldOutMap().put(productId, true);
    44 
    45             //优化2:缓存数据+1(这时stock=-1,还原为0,需要+1)
    46             stringRedisTemplate.opsForValue().increment(PRODUCT_STOCK_KEY + productId);
    47 
    48             //优化4:ConcurrentHashMap是jvm线程同步,如果是多集群分布式服务,还是会造成并发,可以用消息中间件或zooKeeper解决
    49             //获取productId在Zookeeper中的路径
    50             String zkSoldProductPath = Constants.getZkSoldProductPath(productId);
    51             //如果不存在值为true的zookeeper,则添加一个
    52             if (zookeeper.exists(zkSoldProductPath, ture) == null) {
    53                 zookeeper.create(zkSoldProductPath, "true".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode);
    54             }
    55 
    56             return "商品已售完";
    57         }
    58 
    59         try {
    60 
    61             //业务逻辑
    62 
    63             //优化1:操作数据库,-1操作在sql中执行,防止并发(数据库乐观锁)
    64 
    65         } catch (Exception ex) {
    66 
    67             //优化2:秒杀失败,还原stock,需要+1
    68             stringRedisTemplate.opsForValue().increment(PRODUCT_STOCK_KEY + productId);
    69 
    70             //优化3:秒杀失败,这时库存至少为1,移除ConcurrentHashMap值
    71             if (productSoldOutMap.get(productId) != null) {
    72                 productSoldOutMap.remove(productId);
    73             }
    74 
    75             //优化4:修改zk的商品售完标记为false
    76             if (zookeeper.exists(zkSoldProductPath, ture) != null) {
    77                 zookeeper.setData(Constants.getZkSoldProductPath(productId), "false".getBytes(), -1);
    78             }
    79 
    80             return "创单失败";
    81         }
    82         
    83         return "";
    84 
    85     }

    优化一共分为四个方面:

    1.数据库优化:对库存的数据库操作,直接在sql中进行-1,mySql数据库自带乐观锁。(缺点:并发在500-1000左右,最大并发连接数是16384。)

    2.redis缓存:将要对数据库操作的数据放入redis缓存中,先判断缓存中数据是否满足,不行直接return,大大减少了数据库压力。(并发数能达到十万左右,缺点:要考虑redis缓存和mysql数据的一致性)

    3.ConCorrectHashMap集合:线程同步的集合,库存不足时向ConCorrectHashMap集合中添加一个值,先检查ConCorrectHashMap集合是否有值,再检查stock。(解决了redis和mysql数据的一致性,缺点:JVM级别的线程同步,在多集群分布式服务中并不适用)

    4.消息中间件或ZooKeeper:库存不足时向zookeeper中添加一个值,客户端进行监听数据

  • 相关阅读:
    linux 系统账户 和 普通账户 的区别
    supervisor 相关命令
    linux 动态链接库查找方法;查找动态链接库位置; LIBRARY_PATH 和 LD_LIBRARY_PATH 的区别;LD_LIBRARY_PATH and LD_RUN_PATH的区别;MACOS 下查看动态链接库方法
    Ubuntu 一键伪装成Win 10,Kali Linux 2019 kali-undercover软件嫁接;Ubuntu 1804 使用 kali-undercover;
    C 实战练习题目30 – 回文数
    C 实战练习题目29
    C 实战练习题目28
    C 实战练习题目27
    C 实战练习题目26 -递归法求阶乘
    C 实战练习题目25
  • 原文地址:https://www.cnblogs.com/BounceGuo/p/13384334.html
Copyright © 2011-2022 走看看