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

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

《并发扣款,如何保证数据的一致性?》,分享了同一个用户并发扣款时,有一定概率出现数据不一致,可以使用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沈剑提供。

目录
相关文章
|
存储 关系型数据库 MySQL
MySQL的存储过程——流程控制-while、repeat、loop循环
MySQL的存储过程——流程控制-while、repeat、loop循环
972 0
MySQL的存储过程——流程控制-while、repeat、loop循环
|
存储 运维 监控
当游戏爱上MongoDB!阿里云&MongoDB中国区域游戏行业私享会
始于2019年底的新冠疫情改变了我们的生活方式,游戏成为了很多人排遣寂寞的一种方式,由此带来了游戏市场的异常火爆。游戏市场比拼的是谁能更快速地开发迭代,让玩家体验更佳,因此能够敏捷开发、快速扩展、全球部署和轻运维的数据库产品无疑将为游戏的开发和后期运营奠定良好的基础。 诚邀您与Mongo DB、阿里云数据库专家团队, 以及游戏行业同行共同探讨如何使用Mongo DB帮您打造全球化高效、易用、稳定的数据库架构,并为您详细解读MongoDB5.0新特性在游戏行业的最佳实践。
4400 1
当游戏爱上MongoDB!阿里云&MongoDB中国区域游戏行业私享会
|
8月前
|
人工智能 自然语言处理 数据可视化
聊聊多维表格与BI|AI x Data 数据产品的发展趋势
多维表格与Quick BI深度融合,助力企业在AI与数据时代实现高效分析。多维表格作为轻量级数据管理工具,擅长快速填报与基础分析;而Quick BI则专注于多源数据整合、深度洞察与可视化展示。两者协同,既能降低使用门槛,又能提升数据分析的广度与深度,满足企业从数据采集到智能决策的全链路需求。未来,数据产品将朝着低门槛、多场景与实用性方向发展,推动商业智能迈向新高度。
490 25
|
9月前
|
人工智能 运维 数据挖掘
瑶池数据库Data+AI驱动的全栈智能实践开放日回顾
阿里云瑶池数据库重磅推出“Data+AI能力家族”,包括DTS AI数据准备、Data Agent系列智能体及DMS MCP统一数据访问服务,重构数据与AI协同边界。通过智能化工具链,覆盖数据全生命周期,提升企业数据开发、分析、治理与运维效率,降低技术门槛,激活数据资产价值,助力企业迈向全栈智能新时代。
|
10月前
|
人工智能 自然语言处理 架构师
2025年,租赁企业如何借瓴羊Data x AI实现弯道超车?
在新一代技术浪潮下,数据智能正深刻重塑租赁行业。阿里云瓴羊联合得宸科技推出大模型解决方案,助力租赁企业实现智能化转型。通过融合通义千问与专业数据库,方案覆盖经营分析、风险识别等9大场景,推动业务全流程重构,构建以数据驱动和智能引领的增长引擎,赋能行业高质量发展。
517 0
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万级数据统计优化实践
【10月更文挑战第21天】 在处理大规模数据集时,传统的单体数据库解决方案往往力不从心。MySQL和Redis的组合提供了一种高效的解决方案,通过将数据库操作与高速缓存相结合,可以显著提升数据处理的性能。本文将分享一次实际的优化案例,探讨如何利用MySQL和Redis共同实现百万级数据统计的优化。
854 9
|
存储 人工智能 Cloud Native
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
阿里云瑶池在2024云栖大会上重磅发布由Data+AI驱动的多模数据管理平台DMS:OneMeta+OneOps,通过统一、开放、多模的元数据服务实现跨环境、跨引擎、跨实例的统一治理,可支持高达40+种数据源,实现自建、他云数据源的无缝对接,助力业务决策效率提升10倍。
|
存储 人工智能 Cloud Native
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
阿里云数据库重磅升级!元数据服务OneMeta + OneOps统一管理多模态数据
|
关系型数据库 MySQL 测试技术
【专栏】PostgreSQL数据库向MySQL迁移的过程、挑战及策略
【4月更文挑战第29天】本文探讨了PostgreSQL数据库向MySQL迁移的过程、挑战及策略。迁移步骤包括评估规划、数据导出与转换、创建MySQL数据库、数据导入。挑战包括数据类型不匹配、函数和语法差异、数据完整性和性能问题。应对策略涉及数据类型映射、代码调整、数据校验和性能优化。迁移后需进行数据验证、性能测试和业务验证,确保顺利过渡。在数字化时代,掌握数据库迁移技能对技术人员至关重要。
1041 5
|
机器学习/深度学习 算法 自动驾驶
【计算机视觉】Deep SORT多目标跟踪算法讲解(图文解释 超详细)
【计算机视觉】Deep SORT多目标跟踪算法讲解(图文解释 超详细)
2006 0