并发扣款一致性,幂等性问题,这个话题还没聊完!!!

简介: 因此,在有重试的架构体系里,幂等性是需要考虑的一个问题。

《并发扣款,如何保证数据的一致性?》,分享了同一个用户并发扣款时,有一定概率出现数据不一致,可以使用CAS乐观锁的方式,在不降低吞吐量,并且只有少量修改的情况下,保证数据的一致性。


文章发布不到24小时,就有近200的评论。

  其中,问的比较多的是ABA问题,这个问题已经在《并发扣款一致性优化,CAS下ABA问题,这个话题还没聊完!!!》中扩展。   其次,问的比较多的是作业题,为什么一定要用 select&set 的方式进行余额写回:

UPDATE t_yue SET money=$new_money WHERE uid=$uid AND money=$old_money;

  为什么不能采用 直接扣减 的方法:

UPDATE t_yue SET money=money-$diff WHERE uid=$uid;

  很人说,在并发情况下, 会将money扣成负数 。   为了保证余额不被扣成负数,再加一个where条件:

UPDATE t_yue SET money=money-$diff WHERE uid=$uid AND money-$diff>0;

这样是否可行? 画外音:额,撇开业务不谈,这个SQL用列做运算,其实是不好的,建议使用:

UPDATE t_yue SET money=money-$diff WHERE uid=$uid AND money>$diff;

  画外音:说明绝大部分同学,能够回答正确作业。   聊幂等性之前,先看另一个测试用例的case。   假设有一个服务接口,注册新用户:

bool RegisterUser($uid, $name){

         //查看uid是否已经存在

         select uid from t_user where uid=$uid;

         //不是新用户,返回失败

         if(rows>0)return false;

         else{

                   //把新用户插入用户表                    insert into t_user values($uid, $name);                    //返回成功                    return true;          } }   有一个测试工程师,对该接口写了一个测试用例:

bool TestCase_RegisterUser(){

         //造一些假数据

         long uid=123;

         String name='shenjian';

         //调用被测试的接口

         bool result= RegisterUser(uid,name);

         //预期注册成功,对结果进行断言判断

         Assert(result,true);

         //返回测试结果

         return result;

}

  这是不是一个好的测试用例?
这个用例存在什么问题?
你会发现, 相同条件下 ,这个 测试用例执行两次,得到的结果不一样 : (1)第一次执行,第一次造数据,调用接口,注册成功; (2)第二次执行,又造了一次相同的数据,调用接口,注册会失败; 这 不是一个好的测试用例,多次执行结果不同 。   什么是幂等性? 相同条件下,执行同一请求,得到的结果相同,才符合幂等性。 画外音:Google一下,比我解释得更好,但意思应该说清楚了。   如何将上面的测试用例改为符合“幂等性”的测试用例呢?   只需要加一行代码:

bool TestCase_RegisterUser(){

         //造一些假数据

         long uid=123;

         String name=’shenjian’;

         //先删除这个伪造的用户

         DeleteUser(uid);

         //调用被测试的接口

         bool result= RegisterUser(uid,name);

         //预期注册成功,对结果进行断言判断

         Assert(result,true);

         //返回测试结果

         return result;

}

这样,在相同条件下, 不管这个用例执行多少次,得到的测试结果都是相同的 。   是不是对幂等性有点感觉了。   读请求,一般是幂等的。

写请求,视情况而定:
  • insert x,一般来说不是幂等的,重复插入得到的结果不一定一样

  • delete x,一般来说是幂等的,删除多次得到的结果仍相同

  • set a=x是幂等的

  • set a=a-x不是幂等的

  • …

  因此,这么扣减余额: UPDATE t_yue SET money=$new_money WHERE uid=$uid AND money=$old_money; 是幂等操作 。   要是这么扣减余额: UPDATE t_yue SET money=money-$diff WHERE uid=$uid AND money-$diff>0; 不是幂等操作 。   聊到这里,或许有朋友要抬杠了,测试用例会重复执行,扣款怎么会重复执行呢? 重试。   重试,是异常处理里很常见的手段。   你在写业务的时候有没有写过这样的代码:

result = DoSomething();

if(false==result || TIMEOUT){

         //错误,或者超时,重试一次

         result= DoSomething();

}

return result;

  当然,又会有朋友抬杠了,我从来不重试!!! 画外音:额,这是合格,还是不合格呢?   你可以决定业务代码怎么写,你不能决定底层框架代码怎么写: (1) 站点框架 有没有自动重试? (2) 服务框架 有没有自动重试? (3) 服务连接池 , 数据库连接池 有没有自动重试? 画外音: (1)服务化分层的架构中,建议只入口层重试,服务层不要重试,防止雪崩; (2)dubbo底层,调用超时是默认重试的,这个设计不好;   因此,在有重试的架构体系里,幂等性是需要考虑的一个问题。   现在该懂了,为啥扣款和充值业务,一般使用:
  • select&set,配合CAS方案

而不使用:
  • set money-=X方案

画外音:充了100电话费,怎么多了200块?

知其然,知其所以然 ,希望大家有收获。

本文转自“架构师之路”公众号,58沈剑提供。

目录
相关文章
|
Shell
我来教你如何将cpu使用率up起来(shell脚本[含注释])
我来教你如何将cpu使用率up起来(shell脚本[含注释])
1948 0
|
编解码 C++
Google Earth Engine ——1958-2020年TerraClimate 全球陆地表面每月气候和气候水平衡的数据集
Google Earth Engine ——1958-2020年TerraClimate 全球陆地表面每月气候和气候水平衡的数据集
2288 0
Google Earth Engine ——1958-2020年TerraClimate 全球陆地表面每月气候和气候水平衡的数据集
|
6月前
|
Java 关系型数据库 应用服务中间件
阿里云服务器99元1年:经济型e实例,2核2G配置,3M固定带宽,40G云盘,中小应用首选
阿里云推出99元/年经济型e实例云服务器,配置为2核2G、3M固定带宽、40G ESSD Entry云盘,适合个人开发者及中小企业部署轻量级应用。该服务器覆盖多个国内地域,支持“新购续费同价”至2027年3月31日。其具备企业级数据保护能力,稳定可靠,适合网站搭建、开发测试、云上学习等场景,但不适合高并发等重负载场景。
|
6月前
|
缓存 API UED
【开源剪映小助手】核心功能之草稿管理系统
剪映草稿管理系统基于FastAPI与Electron构建,支持草稿全生命周期管理、default2模板迁移、双文件(draft_content.json/draft_info.json)同步及跨平台目录扫描(robocopy/rsync),自动触发剪映/Premiere草稿发现,无需重启,提升创作效率。(239字)
|
6月前
|
人工智能 安全 Linux
阿里云OpenClaw镜像太香了!开箱即用、内置Skills、分钟级部署AI龙虾助理
阿里云OpenClaw镜像基于Alibaba Cloud Linux 3 LTS,开箱即用,阿里云龙虾官方部署链接:https://t.aliyun.com/U/vFiCUH 预装Docker、VS Code等工具及agent-browser等增强Skills,支持钉钉/飞书等多渠道集成与qwen3.5-plus等多模态模型,分钟级部署本地AI助理,安全稳定、计费可控。
544 4
|
7月前
|
人工智能 安全 搜索推荐
🚀 GPT-4.5与Claude 3.7:大模型之战的新篇章
2026年大模型巅峰对决:GPT-4.5强在自然对话、创意生成与视觉叙事;Claude 3.7胜在逻辑推理、长文档分析(200K上下文)及超高性价比(输出成本仅GPT-4.5的20%)。二者共推AI能力边界,选择需匹配场景需求。(239字)
769 2
|
11月前
|
安全 前端开发 NoSQL
诊所his系统源码,门诊系统源码,一级医院信息管理系统源码
云门诊HIS系统,专为中小医疗机构设计,支持中医馆、门诊部等。含预约挂号、电子病历、药品管理、财务统计等功能,Java开发,前后端分离,技术先进,安全高效,易扩展。
394 1
|
10月前
|
存储 资源调度 监控
RFID实现仓库托盘全流程高效管控
RFID托盘管理通过为每个托盘赋予唯一电子标签,实现全流程可视化追踪。利用无线射频技术,批量快速读取信息,提升出入库、盘点、回收等环节效率5-10倍,降低丢失损耗,减少人工错误,推动仓储物流向智能化、数字化转型。(238字)
|
弹性计算 算法 Linux
使用SM4算法加密LUKS格式磁盘
本文介绍了在Anolis 8操作系统使用cryptsetup对磁盘进行分区、加密和挂载的过程。采用SM4加密算法。具体步骤包括:初始化加密卷、解锁加密分区、格式化并挂载设备。最后,展示了如何取消挂载并关闭加密卷以确保数据安全。整个过程确保了磁盘数据的安全性和隐私保护。
1420 2
使用SM4算法加密LUKS格式磁盘
|
存储 关系型数据库 MySQL
PostgreSQL与MySQL优劣势比较浅谈
PostgreSQL与MySQL优劣势比较浅谈
3506 0

热门文章

最新文章