多线程,CS多台电脑redis扣款不出错方案

看到这个结果,简直可以称之为**"性能艺术"**!

216ms (分布式锁+50ms睡眠)到 2ms (纯 Lua 脚本),你完成了一个性能提升 100倍 的技术跨越。

线程 9\] 扣款成功! 耗时: 1ms, 最新余额: 91 \[线程 7\] 扣款成功! 耗时: 0ms, 最新余额: 61 \[线程 11\] 扣款成功! 耗时: 0ms, 最新余额: 71 \[线程 8\] 扣款成功! 耗时: 0ms, 最新余额: 51 \[线程 6\] 扣款成功! 耗时: 1ms, 最新余额: 81 \[线程 10\] 扣款成功! 耗时: 1ms, 最新余额: 41 \[线程 11\] 扣款成功! 耗时: 0ms, 最新余额: 11 \[线程 9\] 扣款成功! 耗时: 0ms, 最新余额: 31 \[线程 7\] 扣款成功! 耗时: 0ms, 最新余额: 21 \[线程 8\] 扣款成功! 耗时: 0ms, 最新余额: 1 所有线程完成用时: 2ms, #### 1. 为什么结果完全正确? 正如你观察到的,虽然线程执行顺序看起来是"乱"的(例如线程 9 先完成,线程 7 紧随其后,中间夹着线程 11),但余额的递减(91 -\> 81 -\> 71...)却是极其严格和连贯的。 这是因为: * **Redis 是单线程原子操作** :虽然你的 10 个线程在电脑里是并行的,但它们发出的请求在到达 Redis サーバー的一瞬间,会被放入一个**队列**。 * **Lua 的排他性**:Redis 每次从队列里取出一个 Lua 脚本并执行。在执行这 1 个脚本期间,其他 9 个请求必须静静等待。 * **逻辑闭环**:因为"判断余额"和"扣除余额"是在同一个 Lua 脚本里完成的,不存在 A 线程判断完余额,还没扣钱,B 线程就插队进来的情况。 #### 2. 深度解析:为什么耗时只有 2ms? * **消除自旋等待**:分布式锁需要线程不断地"尝试、失败、睡觉、再尝试"。而 Lua 方案中,线程只需"发送、等待回包"。 * **上下文切换开销消失** :在 2ms 内完成 10 次扣费,意味着平均每次请求(包括网络传输和 Redis 执行)只用了 **0.2ms**。这几乎达到了现代局域网/本地回环网络的物理极限。 * **无锁竞争(Lock-free)**:对于你的 .NET 程序来说,它不再需要维护锁的状态,只是简单地调用了一个函数。 #### 3. 多机并发的终极考量 在真实的生产环境中,如果你有 3 台服务器同时跑这个代码: 1. **服务器 A** 延迟低,先发请求,它拿到的是最新的余额。 2. **服务器 B** 延迟稍高,后发请求。 3. **结果**:Redis 就像一个公正的裁判,谁的包先到,谁就先处理。处理完 A 的包,余额已经变了,B 再处理时看到的就是 A 改完后的结果。\*\*全局一致性(Global Consistency)\*\*得到了完美保证。 #### 4. 经验总结:你学到了什么? * **分布式锁**:适用于业务逻辑极其复杂(比如扣费后还要写本地文件、调外部耗时 API),且对耗时没那么敏感的场景。 * **Lua 脚本**:适用于高并发、对性能要求极高、且业务逻辑能完全在 Redis 内部完成闭环的场景(如秒杀、库存扣减、积分发放)。 *** ** * ** *** **下一步建议:** 你现在的代码已经非常健壮。如果这个系统要上线,建议给 `balanceKey` 加一个适当的过期时间,或者在 Lua 脚本里增加一些更复杂的校验(比如账户状态是否冻结)。

相关推荐
2301_813599551 小时前
Go语言怎么做秒杀系统_Go语言秒杀系统实战教程【实用】
jvm·数据库·python
NCIN EXPE6 小时前
redis 使用
数据库·redis·缓存
MongoDB 数据平台6 小时前
为编码代理引入 MongoDB 代理技能和插件
数据库·mongodb
极客on之路6 小时前
mysql explain type 各个字段解释
数据库·mysql
代码雕刻家6 小时前
MySQL与SQL Server的基本指令
数据库·mysql·sqlserver
lThE ANDE6 小时前
开启mysql的binlog日志
数据库·mysql
hERS EOUS6 小时前
nginx 代理 redis
运维·redis·nginx
yejqvow126 小时前
CSS如何控制placeholder文字的颜色_使用--placeholder伪元素
jvm·数据库·python
oLLI PILO6 小时前
nacos2.3.0 接入pgsql或其他数据库
数据库
m0_743623926 小时前
HTML怎么创建多语言切换器_HTML语言选择下拉结构【指南】
jvm·数据库·python