首页/新闻资讯/正文详情

零工日结提现:余额、提现单、事务、幂等,我是这么把这笔“钱“管住的

发布时间:2026/9/26 18:45:01 来源:云帆数科 栏目:资讯中心
零工日结提现:余额、提现单、事务、幂等,我是这么把这笔“钱“管住的
零工日结提现余额、提现单、事务、幂等我是这么把这笔钱管住的导读xllg 是日结零工系统工人干完活当天就能提现。涉及钱的逻辑我最怕出 bug——多扣一笔、重复到账、提现单和余额对不上哪一样都够喝一壶的。这篇讲讲提现链路是怎么设计的余额账户 提现单 事务 幂等四层一起上。表结构余额和流水分开余额不能只存一个数字还得有流水可追溯。两张表user_wallet存账户余额wallet_flow存每一笔变动CREATETABLEuser_wallet(idBIGINTPRIMARYKEYAUTO_INCREMENT,user_idBIGINTNOTNULLCOMMENT用户ID,balanceDECIMAL(10,2)NOTNULLDEFAULT0.00COMMENT可用余额,frozenDECIMAL(10,2)NOTNULLDEFAULT0.00COMMENT冻结金额提现中的,versionINTNOTNULLDEFAULT0COMMENT乐观锁版本号,update_timeDATETIMEDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,UNIQUEKEYuk_user(user_id))ENGINEInnoDBDEFAULTCHARSETutf8mb4COMMENT用户余额账户;CREATETABLEwallet_flow(idBIGINTPRIMARYKEYAUTO_INCREMENT,user_idBIGINTNOTNULL,typeTINYINTNOTNULLCOMMENT1收入 2支出 3冻结 4解冻,amountDECIMAL(10,2)NOTNULL,balance_afterDECIMAL(10,2)NOTNULLCOMMENT变动后余额,biz_noVARCHAR(64)NOTNULLCOMMENT业务单号幂等键,create_timeDATETIMEDEFAULTCURRENT_TIMESTAMP,UNIQUEKEYuk_biz(biz_no))ENGINEInnoDBDEFAULTCHARSETutf8mb4COMMENT钱包流水;核心设计流水表的 biz_no 唯一索引就是幂等键同一笔提现重复提交第二次插流水直接报唯一键冲突。提现事务先冻结再记账提现逻辑分两步把可用余额冻结生成提现单。两步必须在一个事务里否则出现钱冻了但单子没建就乱了ServicepublicclassWithdrawService{AutowiredprivateWalletMapperwalletMapper;AutowiredprivateWithdrawMapperwithdrawMapper;AutowiredprivateFlowMapperflowMapper;Transactional(rollbackForException.class)publicvoidapplyWithdraw(LonguserId,BigDecimalamount){// 1. 扣减可用余额、增加冻结带乐观锁防止并发intupdatedwalletMapper.freeze(userId,amount);if(updated!1){thrownewBizException(余额不足或账户被并发修改请重试);}// 2. 生成提现单WithdrawordernewWithdraw();order.setUserId(userId);order.setAmount(amount);order.setStatus(0);// 待打款withdrawMapper.insert(order);// 3. 记流水biz_no 唯一重复提交会失败flowMapper.insert(FlowBuilder.build(userId,3,amount,提现冻结));}}walletMapper.freeze的 SQL 是关键一条 UPDATE 同时完成判断和扣减UPDATEuser_walletSETfrozenfrozen#{amount},versionversion1WHEREuser_id#{userId}ANDbalance#{amount}balance #{amount}条件不满足时影响行数为 0Java 侧拿updated ! 1判断天然防住余额不够还提现和并发扣超。踩坑事务方法内部调自己Transactional 失效现象提现接口偶发出现余额扣了但提现单没生成的情况。查库发现 wallet_flow 有冻结流水、user_wallet 余额也减了但 withdraw 表里没有对应记录。排查先看日志报的是NullPointerException——插入提现单前取用户信息时空指针。关键问题是异常抛出来了但余额已经扣了说明事务没回滚。再看代码发现applyWithdraw是被同一个类里的另一个方法handleWithdrawRequest通过this.applyWithdraw()调用的。定位这就是经典的自调用问题——Transactional依赖 Spring 代理this.xxx()是直接调用原始对象的方法代理根本不参与事务注解形同虚设异常自然不会回滚。解决把提现事务方法拆到独立 Service或者通过注入自己的代理调用ServicepublicclassWithdrawService{// 通过 AopContext 拿代理调用自己保证事务生效Transactional(rollbackForException.class)publicvoidapplyWithdraw(LonguserId,BigDecimalamount){// ...冻结 建单 流水}publicvoidhandleWithdrawRequest(LonguserId,BigDecimalamount){// 需要事务的方法必须经过代理((WithdrawService)AopContext.currentProxy()).applyWithdraw(userId,amount);}}改造后测试验证人为制造异常余额、提现单、流水全部回滚三者保持一致。可直接复用的清单余额和流水分表余额是结果、流水是证据对账靠流水扣余额的 SQL 把判断 扣减合到一条 UPDATE影响行数做并发控制提现单用biz_no唯一索引做幂等重复提交直接冲突报错事务方法禁止自调用必须经过 Spring 代理才生效金额一律用DECIMAL禁止 float/double精度问题都是血泪这套提现链路在 xllg 里上线后对账单月月能对上没出过一次金额纠纷。涉及钱的功能宁可多写一层幂等也别赌不会重复提交。项目源码https://gitee.com/gzqkl/xllg

相关推荐

TypeScript类型守卫与类型缩小:告别as断言的实战指南
TypeScript类型守卫与类型缩小:告别as断言的实战指南

TypeScript 写久了,你会发现真正决定一个项目代码质量上限的,往往不是泛型玩得有多花,而是类型守卫和类型缩小这两件事做得够不够细。我见过不少项目,接口定义写得很全,但一到业务分支里就全是as any、as SomeType&… · 2026/9/26 18:45:01

TypeScript类型守卫与类型缩小:原理、实战与工程化设计指南
TypeScript类型守卫与类型缩小:原理、实战与工程化设计指南

类型守卫和类型缩小这两个词,你在 TypeScript 的官方文档、技术帖和同事的代码评审意见里应该都见过。但很多人对它们的理解停留在"哦,就是 typeof 判断一下类型",真到了写复杂业务代码时,照样会被 TS 报错卡住&#xf… · 2026/9/26 18:45:01

自己写的论文AI率也很高,怎么改才能降低AIGC疑似度?
自己写的论文AI率也很高,怎么改才能降低AIGC疑似度?

自己写的论文AI率也很高,怎么改才能降低AIGC疑似度? 资料是自己找的,访谈是自己做的,论文也是一段段写出来的,检测报告却把不少内容标成高疑似。最难受的不是看到一个数字,而是不知道哪里出了问题&#xf… · 2026/9/26 18:44:54

FME转换器实战指南:高频Transformer选型、PythonCaller与性能避坑
FME转换器实战指南:高频Transformer选型、PythonCaller与性能避坑

简介:这份《2022FME转换器快速参考手册-中文版》面向使用FME Workbench进行空间数据转换与集成的GIS从业者、数据处理工程师及初学者,帮助读者快速查阅各类转换器的功能定位与适用场景,解决转换器数量庞大、英文文档查阅不便的问题。资源包共… · 2026/9/26 19:20:53

NetWatch解密你的HTTPS流量:SSLKEYLOGFILE配置TLS 1.3/1.2与QUIC解密完整教程
NetWatch解密你的HTTPS流量:SSLKEYLOGFILE配置TLS 1.3/1.2与QUIC解密完整教程

NetWatch解密你的HTTPS流量:SSLKEYLOGFILE配置TLS 1.3/1.2与QUIC解密完整教程 【免费下载链接】netwatch Real-time network diagnostics in your terminal. One command, zero config, instant visibility. 项目地址: https://gitcode.com/gh_mirrors/netwatc/ne… · 2026/9/26 19:20:53

ET-BAG CAD出格系统教程:智能笔操作与纸格生成全流程
ET-BAG CAD出格系统教程:智能笔操作与纸格生成全流程

简介:这份PDF教程面向服装打版师、CAD设计初学者及希望提升出格效率的从业者,系统讲解ET-BAG软件CAD出格系统的操作方法与技巧。内容从智能笔的左键、右键点选两类用法切入,延伸至直线与弯线绘制、丁字尺角度线、曲线加点减点与端固定修正、群… · 2026/9/26 19:20:53

Mac自定义快捷键三层体系:系统层、应用层与脚本层实战指南
Mac自定义快捷键三层体系:系统层、应用层与脚本层实战指南

1. 为什么系统自带的快捷键设置根本不够用Mac 的键盘快捷键体系,表面看是苹果“开箱即用”的优雅代表——Mission Control、Spotlight、截图、音量调节,一按即达。但真正用上三个月后,几乎每个认真工作的人都会发现:系统设置里那几… · 2026/9/26 19:20:38

华为Atlas 300V部署YOLO实战:从ONNX到OM完整指南
华为Atlas 300V部署YOLO实战:从ONNX到OM完整指南

1. Atlas到底是什么,它是“运算加速卡”吗先说结论:Atlas 300V 24G就是一块正儿八经的云端AI推理加速卡,网上总有人在问“atlas 300v 24g 是运算加速卡吗”,我估计是名字里带“V”让人犯迷糊,以为它是什么显卡或显示加… · 2026/9/26 19:20:38

telnet端口连通性诊断:TCP层网络排查核心工具
telnet端口连通性诊断:TCP层网络排查核心工具

1. 这不是“老古董”,而是你每天都在用却没真正搞懂的端口诊断利器很多人看到telnet这个词,第一反应是“这玩意儿不是90年代就该进博物馆了吗?”——尤其在 Windows 系统里,默认根本不开,点开 CMD 输telnet直接报错“不… · 2026/9/26 19:20:38

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码