zoukankan      html  css  js  c++  java
  • 库存负数

    库存负数

    • 场景:

    当==多用户==并发点击参与活动,如:抽奖活动,这个时候奖品只有一个库存了,理论上只有一个用户可以获得,但是并发的时候往往会出现他们都成功获得奖品,导致奖品多支出,加大了活动成本

    • 剖析:

    有问题的逻辑流程一般是这样的:

    中奖 --> 查询奖品库存 --> 有 --> 更新奖品库存 --> 添加中奖纪录 --> 告知中奖
    中奖 --> 查询奖品库存 --> 无 --> 告知无中奖

    假设抽奖活动,当前奖品A只有最后一个库存,然后用户A、B、C,同时参与活动同时中奖奖品都是A,这个时候查询商品库存是存在1个,就会进行更新库存,添加中奖纪录,然后就同时中奖了

    • 解决方案:

    最理想根本就不需要用多做一个库存的SELECT奖品库存操作,只需要UPDATE 奖品库存-1 WHERE 奖品库存>=1,UPDATE成功后就说明是有库存的,然后再做后续操作,并发的时候只会有一个用户UPDATE成功


    • 方案1
      • [主动]后台点击更新缓存按钮,从DB查找最新数据集合,删除原缓存数据,存储新数据到缓存;
      • 问题:更新过程中删除掉缓存后刚好有业务在查询,那么这个时候返回的数据会是空,会影响用户体验

    • 方案2
      • [被动]前台获取数据时发现没有缓存数据就会去数据库同步数据到缓存
      • 问题:当并发请求获取缓存数据不存在的时候,就会产生并发的查询数据的操作。

    • 方案3
      • [主动]后台点击更新缓存按钮,从DB查找最新数据集合,这里不删除缓存,通过遍历数据覆盖和删除掉无效的数据
      • 问题:逻辑相对麻烦,而且更新机制无法通用;

    推荐


    以上的几种更新方案我都遇到过,因为产生了各种问题,所以我想到了一个相对好的方案,类似预加载功能,先把数据加载到缓存中,缓存成功后再切换显示最新的数据,将旧数据设置过期;

    • 方案4
      [主动][预加载]前台获取缓存的时候需要先得到缓存数据对应的Redis Key(简称:[ShowingKey]),然后根据[ShowingKey]去读取缓存数据(简称:[缓存];
      • 需要两块数据:
        • [ShowingKey](可以是最近一次更新缓存的时间戳或者根据自己规则自定义)
        • [缓存](需要缓存的数据,如:DB数据等)

      • 举个栗子:
        我们现在有个业务需要缓存今日上新商品数据,缓存到Hash中

        • [缓存]对应Redis Key 规则
          • Hash Key=Goods:Todays:{0} {0}=时间戳
        • [ShowingKey]对应的Redis Key
          • Key string key=Goods:Todays:ing 内容=最近一次的更新时间戳

        更新逻辑:

        后台编辑人员操作完数据的时候点击更新按钮,获取服务器当前时间=1469938351000=[更新时间戳],然后获取DB数据,缓存到Goods:Todays:1469938351000中,添加缓存数据成功后,获取Goods:Todays:ing中的时间戳1449538371020=[上一次更新时间戳],更新Goods:Todays:ing值=[更新时间戳]=1469938351000,更新成功后可以把[上一次更新时间戳]对应的缓存设置过期时间,我一般是设置5秒后过期。(注意旧数据一定要设置过期时间,不能直接删除,因为在切换[ShowingKey]的过程中可能还有业务在使用)

        数值累加,get,set+1并发导致累加不准确

        • 使用redis increment 自增数值的机制不会有累加不准确的问
        • ++++++++++++++
           

          综合套路

          • 图片地址独立域名
            • 与业务不同域名可以减少请求头里不必要的cookie传输
  • 相关阅读:
    POJ 3672 水题......
    POJ 3279 枚举?
    STL
    241. Different Ways to Add Parentheses
    282. Expression Add Operators
    169. Majority Element
    Weekly Contest 121
    927. Three Equal Parts
    910. Smallest Range II
    921. Minimum Add to Make Parentheses Valid
  • 原文地址:https://www.cnblogs.com/agang-php/p/9810677.html
Copyright © 2011-2022 走看看