因为一个Bug,差点损失了100w

大家好,我是洋子

最近在做单接口的性能测试比较多,在压测过程发现了一个比较有意思的问题,拿出来和大家分享一下

背景是这样的,最近在搞线上的抽奖活动,压测的对象是一个抽奖接口,主要的逻辑见程序的流程图

请添加图片描述

  • 这个抽奖的接口逻辑是先通过检查Redis里面存入的已发放奖品数量

  • 查出已发放奖品数量后,与活动配置当中的奖品库存进行对比

  • 若无库存,此时已发放的奖品数量大于了活动预先配置的奖品库存,那么返回库存为空的信息

  • 若还有库存,在Redis里面新增本次中奖的用户信息,设置Redis过期时间,接着进入后续发奖品的逻辑(写DB,修改发送状态等)

在无并发(同一时间内只有一个用户请求)的场景下,这样处理并没有问题,但是在压测当中,有并发请求的场景下,我发现DB里面写入超出库存数量的记录,换句话说上面通过Redis检查库存,拦截多发奖的逻辑存在Bug,没有正常拦截

通过Review代码,我发现这段检测库存的逻辑Redis 的zCard查询,再zAdd插入,为非原子性操作,zCard与zAdd为串行执行,在并发场景下,zCard可能查出的库存是相同的,如活动配置的库存为6,有10个并发用户同时查询出当前已抽奖品数量为5,因为总库存6>已抽奖品数5,当前还有剩余库存,则正常为这10个并发用户发送奖品

        // 查Redis:当前活动已抽出的奖品数量
        $strKey   = sprintf(PrizeStockKey, PrizeInfo_Id, $strDayTime);
        $intStock = $daoRedis->zCard($strKey);
        // 检查当前库存,是否超过活动预先配置的库存
        if($intStock >= $arrPrizeInfo['stock']) {
            Log::warning("the stock empty");
            return $Output;
        }
        $ret = $daoRedis->zAdd($strKey, $intUserId, $intTime);
        //后续逻辑:写DB发送奖品,此处省略

超发奖品这样的逻辑显然是不符合预期的,那我们该如何修改呢,先zAdd再zCard,行不行呢,答案也是不可以,因为先zAdd可能会导致所有用户均无法进行奖品发送

举个例子,总库存为6,此时并发10个用户进行zAdd,再进行zCard 查询为10,超过总库存,此时程序认为奖品已经发完,无法正常发奖

    // 查Redis:当前活动已抽出的奖品数量
    $strKey   = sprintf(PrizeStockKey, PrizeInfo_Id, $strDayTime);
    //先zAdd,再查询zCard
    $ret = $daoRedis->zAdd($strKey, $intUserId, $intTime);
    $intStock = $daoRedis->zCard($strKey);
    // 检查当前库存,是否超过活动预先配置的库存
    if($intStock > $arrPrizeInfo['stock']) {
        Log::warning("the stock empty");
        return $Output;
    }
    //后续逻辑:写DB发送奖品,此处省略

产生这样的现象,归根结底还是以上逻辑Redis都是非原子操作,我们先了解一下什么是原子操作

原子操作是指在计算机科学中的一种操作方式,它被设计成在执行期间不可中断的单个操作。原子操作要么完全执行,要么完全不执行,不会出现中间或部分执行的情况。原子操作通常用于多线程或并发编程中,用于确保共享资源的一致性和并发访问的正确性

原子操作的特点

  • 原子性:原子操作是不可分割的单个操作,要么全部执行成功,要么全部不执行。没有其他线程能够观察到原子操作的中间状态

  • 独立性:原子操作是独立于其他操作的,不受其他线程的干扰或影响。原子操作的执行不会受到并发环境的影响。

原子操作的作用

可以用于实现对共享数据的互斥访问,以避免竞态条件(race condition)的发生。竞态条件是指多个线程对同一共享资源进行并发访问时可能导致的不确定或不正确的结果

常见的原子操作类型

原子读取(atomic read)、原子写入(atomic write)、原子递增(atomic increment)、原子比较并交换(atomic compare-and-swap)等。这些操作通常由硬件或操作系统提供支持,以确保其执行的原子性。

为了修复此问题,我们将zCard和zAdd改成incrBy即可解决上面的问题,因为Redis的incrBy是原子操作,在并发场景也不会出现因并发访问而导致的数据不一致或竞态条件问题

		//写redis:当前奖品抽出数量+1
		$intStock = $daoRedis->incrBy($strKey, 1);
        // 检查当前库存,是否超过活动预先配置的库存
  		if($intStock >= $arrPrizeInfo['stock']) {
            Log::warning("the stock empty");
            return $Output;
        }
        //后续逻辑:写DB发送奖品,此处省略

结束语

完事后,我仔细想想,还好通过这次压测,发现了这个问题,要是活动当中本来发1w现金,最后发成了100w,那我不直接被开了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/21666.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vmware Linux磁盘空间扩容

Linux磁盘空间扩容 VMware虚拟机中配置(1)进入虚拟机设置界面,选择扩展磁盘容量。(2) 本次是在原来30G的基础上扩展为50G。 Linux中设置(1) 可以看出sda3是根分区,下面按照博客提示&…

KVM(二)命令行新建虚拟机

目录 一、准备工作 二、新建虚拟机 2.1 文件准备 2.2 正式安装 2.3 时区设置 2.4 安装设置 2.5 设置root用户密码 2.6 vm2安装完成 三、进入虚拟机vm2 四、网络设置 五、参考链接 若还未部署KVM,请参考第一节: KVM(一)…

python数据可视化显示(附代码)

Python是一种非常流行的编程语言,具有广泛的应用领域,包括数据可视化。在数据可视化中,Python提供了多种工具来帮助用户创建各种类型的图表、图形和可视化效果。本文将介绍Python数据可视化的基本概念、工具和技术,并提供代码示例…

(转载)MATLAB智能算法30个案例分析(1)——遗传算法工具箱

以下内容大部分来源于《MATLAB智能算法30个案例分析》,仅为学习交流所用。 1理论基础 1.1遗传算法概述 遗传算法(genetic algorithm,GA)是一种进化算法,其基本原理是仿效生物界中的“物竞天择、适者生存”的演化法则。遗传算法是把问题参数编码为染色体,再利用迭代…

论文阅读_语音合成_Spear-TTS

论文信息 number headings: auto, first-level 2, max 4, _.1.1 name_en: Speak, Read and Prompt: High-Fidelity Text-to-Speech with Minimal Supervision name_ch: 说话、阅读和提示:少量监督实现高保真文本转语音 paper_addr: http://arxiv.org/abs/2302.0354…

windows11下系统睡眠状态被UpdateOrchestrator唤醒的解决方案

windows11下系统睡眠状态被UpdateOrchestrator唤醒的解决方案 一、问题排查二、问题解决 一、问题排查 最近win11更新后发现会偶尔在睡眠状态下唤醒,CMD中输入powercfg -lastwake命令可以查看唤醒源程序 这里显示唤醒是按下了电源按钮,符合我此次唤醒操…

验证知识点总结

1、常用总线对比 AMBA (Advanced Microcontroller Bus Architecture) 高级处理器总线架构 AHB (Advanced High-performance Bus) 高级高性能总线 ASB (Advanced System Bus) 高级系统总线 APB (Advanced Peripheral Bus) 高级外围总线 AXI (Advanced eXtensible Interface) 高…

系统分析师(一)软考简介

目录 1.证书简介2.考试简介3.考试报名4.各地考试机构5.考试要求6.考试教程用书 考试时间: 每年5月的最后一个周六 1.证书简介 ​ 软考全称是计算机技术与软件专业技术资格(水平)考试,是由国家人力资源和社会保障部、工业和信息化部…

华丽家族股东大会21项议案全被否

5月17日晚间,A股上市公司华丽家族发布关于收到上海证券交易所监管工作函的公告,交易所对相关事项提出监管要求。 在此之前,华丽家族当天召开股东大会,21项股东大会议案全部未通过。历史上,股东大会议案全部被否的情形…

【数据结构】红黑树

文章目录 1. 红黑树的概念与性质1.1 概念1.2 性质 2. 红黑树的实现2.1 节点和结构的定义2.2 红黑树的节点插入(重点!!!!) 3. 红黑树的验证与性能分析3.1红黑树的验证3.2红黑树的性能分析——与AVL树的对比3.3红黑树的应用 1. 红黑…

ECharts

ECharts 一、引言ECharts介绍快速上手 一、引言 ECharts介绍 ECharts是一款基于JavaScript的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。ECharts最初由百度团队开源,并于2018年初捐赠给A…

一文读懂!RK3668和RK3568有什么区别?

​ 从上图可以看出,RK3568和RK3566 CPU均为四核Cortex-A55架构,GPU为Mali-G522EE,内置NPU,可提供1T算力,支持DDR及CPU Cache全链路ECC等,RK366与RK3568最大区别的是RK3568具有PCIe接口、双千兆以太网和更…

如何轻松掌握接口测试——POST请求和COOKIE使用技巧?

目录 引言 请求方法: POST请求方法:添加资源(对服务端已存在的资源也可以做修改和删除操作) 实战练习 实战练习2 COOKIE: Status Code:协议状态码 接口文档 结语 引言 对于初学者或者没有接口测试…

box的符号距离函数

序 能用解析的方法算的,叫符号距离函数。只能数值解的,叫符号距离场。 它就是横平竖直的几个平面,点到平面的距离是很好算的。 初步认识 有个网页,可以玩一玩: About | Physics Simulation in Visual Computing (…

【LeetCode20】有效的括号——图解

​ 你好,欢迎来到我的博客!作为一名程序员,我经常刷LeetCode题目来提升自己的编程能力。在我的博客里,我会分享一些我自己做过的题目和解题思路,希望能够帮助到大家。今天,我想和大家分享一道挑战性较高的题…

Flutter项目webview加载没有HTTPS证书的网页在Android和iOS设备上无法显示的解决方案

一、问题描述 Flutter项目使用谷歌官方webview库 webview_flutter,加载自签名证书、证书失效、无证书等HTTPS网页地址时,在Android或pc浏览器中提示证书失效,在iOS设备上为空白页,为了加载自签名证书的网页,需要饶过i…

Godot引擎 4.0 文档 - 循序渐进教程 - 脚本语言

本文为Google Translate英译中结果,DrGraph在此基础上加了一些校正。英文原版页面: Scripting languages — Godot Engine (stable) documentation in English 脚本语言 本课将概述 Godot 中可用的脚本语言。您将了解每个选项的优缺点。在下一部分中&…

平板触控笔要原装的吗?苹果平替笔性价比高的推荐

与苹果的电容笔不同,市场上的电容笔只会给人一种倾斜的压感,并不会像苹果的电容笔那样,可以给人一种重力的压感。不过,如果你不一定要画画,那你就不用花很多钱去买一支苹果的原装电容笔了,只需一支平替电容…

postgresql数据库

官方文档:link 安装及简单操作 1 安装 sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm sudo yum install -y postgresql15-server sudo /usr/pgsql-15/bin/postgresql-15-setup initdb sudo …

2023.5.21 第五十四次周报

目录 前言 文献阅读:跨多个时空尺度进行预测的时空 LSTM 模型 背景 本文思路 本文解决的问题 方法论 SPATIAL 自动机器学习模型 数据处理 模型性能 代码 用Python编写的LSTM多变量预测模型 总结 前言 This week, I studied an article that uses LSTM to solve p…