PHP 并发扣款,保证数据一致性(悲观锁和乐观锁)
查询商品价格,例如70元。 比较商品价格和用户余额,判断是否足够扣款。 并发查询:用户并发购买业务A和业务B,查询余额时可能显示100元。 扣款处理:业务A扣款后余额变为30元,业务B扣款后余额变为20元。 数据不一致:由于并发处理,系统可能会显示余额更新失败或不一致。
发布日期:2025-05-03 00:43:36
浏览次数:12
分类:精选文章
本文共 1700 字,大约阅读时间需要 5 分钟。
PHP 并发扣款中的数据一致性问题
在用户购买商品的逻辑中,需要对用户钱包的余额进行查询和扣款。然而,在并发处理的情况下,可能会出现数据不一致的情况。这种情况可能会导致用户购买多个商品时,系统显示余额不一致,影响用户体验。
扣款场景
扣款过程分为以下几个步骤:
查询余额:从数据库中查询用户的钱包余额。
SELECT balance FROM user_wallet WHERE uid = $uid;
例如,查询结果为余额100元。
业务逻辑:
if (goodsPrice <= userBalance) { $newUserBalance = userBalance - goodsPrice;} else { throw new UserWalletException(['msg' => '用户余额不足']);} 扣款提交:将数据库中的余额进行修改。
UPDATE user_wallet SET balance=$newUserBalance WHERE uid = $uid;
例如,扣款后余额变为30元。
异常场景
在并发处理中,可能会出现以下情况:
解决方案
为了解决并发扣款中的数据一致性问题,可以采用以下两种方法:
悲观锁
使用Redis的悲观锁,确保在并发处理中只允许一台服务器对数据进行操作。
use Ar414\RedisLock;$redis = new \Redis();$redis->connect('127.0.0.1', '6379');$lockTimeOut = 5;$redisLock = new RedisLock($redis, $lockTimeOut);$lockKey = 'lock:user:wallet:uid:1001';$lockExpire = $redisLock->getLock($lockKey);if ($lockExpire) { try { // 查询用户钱包余额 $userBalance = 100; // 查询商品价格 $goodsPrice = 80; if ($userBalance >= $goodsPrice) { $newUserBalance = $userBalance - $goodsPrice; // 更新数据库 $redisLock->releaseLock($lockKey, $lockExpire); } else { throw new Exception('用户余额不足'); } } catch (\Throwable $throwable) { $redisLock->releaseLock($lockKey, $lockExpire); throw new Exception('网络问题'); } 乐观锁
使用Redis的乐观锁(CAS,Compare And Set),在写入数据时进行版本检查,确保数据一致性。
UPDATE user_wallet SET balance=$newUserBalance WHERE uid = $uid AND balance = $oldUserBalance
这样可以确保并发处理中只有一台服务器能够成功写入数据。
结语
在并发处理中,数据一致性是一个关键问题。选择适合的锁机制可以有效避免数据不一致的情况。然而,使用Redis的悲观锁可能会带来较高的吞吐量压力。因此,需要根据实际情况选择合适的解决方案。
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2026年06月02日 10时41分46秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
php 标准规范
2023-02-28
PHP 浮点型精度运算相关问题
2023-02-28
php 浮点型计算精度问题
2023-02-28
php 特定时间段统计,jpgraph某个时间段的数据统计
2023-02-28
php 生成csv mac下乱码
2023-02-28
php 生成证书 签名及验签
2023-02-28
PHP 的标准输入与输出
2023-02-28
php 笔记 (早前的,很乱)
2023-02-28
PHP 第一天
2023-02-28
Redis使用量暴增,快速定位有哪些大key在作怪
2023-02-28
PHP 统计数据功能 有感
2023-02-28
SpringBoot处理JSON数据
2023-02-28
Redis使用基本套路
2023-02-28
php 解决项目中多个自动加载冲突问题
2023-02-28
PHP 设置调试工具XDebug PHPStorm IDE
2023-02-28
PHP 输入输出流合集
2023-02-28
PHP 面向对象 final类与final方法
2023-02-28
php--防止sql注入的方法
2023-02-28
php-兔子问题,斐波那契数列
2023-02-28