当前位置: 首页 > news >正文

为什么双十一零点你抢不到票?

🔒 事务:最初的“一手交钱一手交货”

在业务看来,转账就是原子操作:A 少钱,B 多钱。要么都成功,要么都失败,绝不能出现 A 扣了钱 B 没收到的情况。

动作代码行数 (理想状态)描述
开启事务1 行BEGIN TRANSACTION;
扣钱1 行UPDATE account SET balance = balance - 100 WHERE id = A;
加钱1 行UPDATE account SET balance = balance + 100 WHERE id = B;
提交1 行COMMIT;

总计:4 行 SQL。

程序员觉得这逻辑完美无缺。直到并发(Concurrency)这个恶魔降临。


⚛️ 第一关:原子性的代价 (Atomicity)

刚上线,服务器断电了。

  • A 的钱扣了。
  • 电断了。
  • B 的钱没加上。
  • 结果:100 块钱凭空蒸发了。用户打爆了客服电话。

代码增加:你必须引入复杂的回滚机制 (Rollback)。在代码里包裹try-catch,一旦第二步报错,必须把第一步扣的钱吐出来。如果数据库本身挂了,还得靠日志(Redo Log/Undo Log)恢复。+30 行异常处理逻辑。


👻 第二关:脏读与幻读的迷魂阵 (Isolation)

为了快,数据库允许很多人同时读写。

  • 脏读:事务甲正在改 A 的余额(还没提交),事务乙读取了 A 的余额。结果事务甲回滚了!事务乙读到的是假数据。
  • 幻读:事务甲查了一下:“现在有 3 个订单”。事务乙突然插进去新增了一个订单。事务甲一回头:“怎么变成 4 个了?见鬼了?”

代码增加:你开始调整隔离级别 (Isolation Level)

  • 级别越高(如 Serializable),数据越安全,但速度越慢(排队)。
  • 级别越低(如 Read Committed),速度越快,但全是 Bug。
    你需要在性能和数据准确性之间走钢丝。+N 行配置和锁策略分析。

🔫 第三关:死锁——墨西哥僵局 (Deadlock)

这是最经典的灾难。两个线程同时操作,互相卡死。

场景:两个人同时转账。

  • 线程 1 (A 转给 B):
  1. 锁住 A(扣钱)。
  2. 准备去锁 B(加钱)。
  • 线程 2 (B 转给 A):
  1. 锁住 B(扣钱)。
  2. 准备去锁 A(加钱)。

僵局:

  • 线程 1 拿着 A,瞪着 B。
  • 线程 2 拿着 B,瞪着 A。
  • 谁也不松手,谁也走不掉。

后果:
数据库连接被这两个人占着,永远不释放。后续的请求全部排队,直到连接池爆满,全站瘫痪

代码增加:强制规定**“加锁顺序”。所有转账必须先锁 ID 小的,再锁 ID 大的**。
if (idA < idB) { lock(A); lock(B); } else { lock(B); lock(A); }
+20 行逻辑判断,且很容易写错。


🚧 第四关:全表锁的误杀 (Table Lock)

你写了个 SQL:UPDATE account SET balance = balance - 100 WHERE name = '张三';
注意:你用了name,但name字段没有索引

数据库的逻辑:
“你要锁张三?但我不知道张三在哪行啊。为了防止你改错,我先把整张表锁起来吧!”

后果:
一个人买牛奶(锁表),导致全超市的人都不能结账。
本来是行级锁(Row Lock),瞬间升级为表级锁(Table Lock)。系统吞吐量从 10000 QPS 跌到 1 QPS。

代码增加:疯狂补索引,做 Explain 分析,严禁在事务中使用非索引字段作为条件。+DBA 的咆哮。


🕸️ 第五关:分布式事务的深渊 (Distributed Transaction)

系统做大了,拆成了微服务。

  • 账户服务在数据库 A。
  • 积分服务在数据库 B。
  • 本地事务(@Transactional)失效了!因为它管不了两个数据库。

后果:
钱扣了(库 A),积分没加(库 B 挂了)。
你不能回滚库 A,因为那是别人的库。

代码增加:欢迎来到地狱。

  • TCC (Try-Confirm-Cancel):每个接口都要写三个方法:预留、确认、撤销。
  • Seata / 2PC:引入沉重的分布式事务框架。
  • 最终一致性:写消息队列,不断重试,告诉用户“处理中”,其实是后台在疯狂补救。
    代码量翻倍,逻辑复杂度指数级上升。

💡 结论:锁是必要的恶

最终,那个理想中“A 减钱,B 加钱”的简单逻辑,变成了:

  • 防丢失:事务回滚。
  • 防错乱:隔离级别。
  • 防卡死:顺序加锁。
  • 防误伤:索引优化。
  • 防分裂:分布式事务补偿。

为什么双十一零点下单那么卡?
不是因为服务器运算慢,是因为成千上万个线程正在争抢那几把“数据库锁”
为了不把钱算错,数据库必须让大家排队。

最扎心的真相:
有时候为了解决死锁,我们唯一的办法就是——杀掉其中一个事务(超时报错),告诉用户:“系统繁忙,请稍后再试”。
这就是为什么你抢票时会莫名其妙失败,那是系统为了救活其他人,把你“牺牲”了。

http://www.jsqmd.com/news/267775/

相关文章:

  • 【收藏必备】ReAct范式详解:从入门到实践,让大模型拥有推理与行动能力
  • git: merge所做修改用git log -p看不到
  • Nginx 为什么用漏桶,而 Guava 用令牌桶?一文看懂限流算法的底层逻辑
  • 学霸同款2026 AI论文平台TOP9:本科生毕业论文写作全测评
  • vue3基于Python协同过滤算法的图书馆图书借阅推荐系统设计与实现217413115
  • 宿迁市宿城宿豫沭阳泗阳泗洪区英语雅思培训辅导机构推荐,2026权威出国雅思课程中心学校口碑排行榜 - 老周说教育
  • 用 MySQL SELECT SLEEP() 优雅模拟网络超时与并发死锁
  • vue3-python县志捐赠与借阅信息管理系统的设计与实现16069432
  • Kali Linux 内网渗透:深度工程实施手册
  • 多智能体协作驱动的多模态医疗大模型系统:RAG–KAG双路径知识增强与架构的设计与验证(上)
  • 避坑指南:精准度高、售后好的国产不锈钢电子地磅品牌推荐,上海花潮实业实力解析 - 品牌推荐大师1
  • 【教程4>第10章>第22节】基于FPGA的图像Laplace边缘提取算法开发——Laplace拉普拉斯卷积运算模块
  • 深入解析:概率论与数理统计第一章 概率论的基本概念
  • 软件测试在职人员,如何持续学习?
  • 技术文章:解决 PowerShell 模块加载无响应问题的实用指南
  • 2026国内最新螺丝定制厂家最新top5排行榜发布!广东等地优质组合螺丝/端子螺丝/螺丝定制/螺丝加工公司及供应商综合实力盘点 - 品牌推荐2026
  • 提拔快的项目经理,打死也不会告诉别人的3个反向操作!
  • 探讨忻州比较好的geo推广机构情况,如何选择 - 工业品牌热点
  • 大模型学习指南:10个核心概念详解,收藏学习不走弯路
  • AI一周重要会议和活动概览(1.19-1.25)
  • vLLM模型脚本目录规范
  • 基于51/STM32单片机交流直流电压电流电表功率电量过载抄表无线设计(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码
  • 2026年AI搜索优化推荐:基于垂直行业实战排名,涵盖B2B与消费场景获客痛点 - 十大品牌推荐
  • 黄金票据是什么
  • STM32智能PID无刷电机PWM调速正反转设计(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码
  • USB口OVP过压保护芯片
  • STM32单片机心率血氧血压温度检测082X(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码
  • 2026年自学网络安全入门教程(非常详细)从零基础入门到精通,看完这一篇就够了
  • 2026年背胶魔术贴厂家最新推荐:切片魔术贴、家居用魔术贴、射出钩魔术贴、纱网魔术贴、背靠背魔术贴、防蚊类魔术贴选择指南 - 优质品牌商家
  • OPC全流程AI agents