news 2026/6/10 17:19:28

零基础从零到一PHP开发仿12306系统的庖丁解牛

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
零基础从零到一PHP开发仿12306系统的庖丁解牛

12306 的本质是高并发、强一致性、分布式事务的票务系统


一、核心认知:12306 的本质是什么?

▶ 1.业务本质
  • 核心实体
    • 车次(Train)
    • 座位(Seat)
    • 订单(Order)
  • 核心流程

    查询余票

    锁定座位

    支付

    生成电子票

▶ 2.技术挑战
挑战初学者简化方案
高并发单机 MySQL + 乐观锁
分布式事务本地事务 + 补偿机制
余票计算预分配座位池

💡核心原则
先实现单机版,再考虑分布式


二、阶段 1:单机 MVP(1 天)

▶ 1.数据库设计
-- 车次表CREATETABLEtrains(idINTPRIMARYKEYAUTO_INCREMENT,train_noVARCHAR(20)NOTNULL,-- G1234departureVARCHAR(50)NOTNULL,-- 北京南arrivalVARCHAR(50)NOTNULL,-- 上海虹桥depart_timeDATETIMENOTNULL);-- 座位表(预分配)CREATETABLEseats(idINTPRIMARYKEYAUTO_INCREMENT,train_idINTNOTNULL,seat_noVARCHAR(10)NOTNULL,-- 05车12AstatusTINYINTDEFAULT0,-- 0=可用, 1=已锁定, 2=已售FOREIGNKEY(train_id)REFERENCEStrains(id));-- 订单表CREATETABLEorders(idVARCHAR(32)PRIMARYKEY,-- UUIDuser_idINTNOTNULL,train_idINTNOTNULL,seat_idINTNOTNULL,statusTINYINTDEFAULT0,-- 0=待支付, 1=已支付created_atDATETIMEDEFAULTCURRENT_TIMESTAMP,FOREIGNKEY(seat_id)REFERENCESseats(id));
▶ 2.PHP 基础代码(无框架)
  • db.php(数据库连接):

    <?php$pdo=newPDO('mysql:host=localhost;dbname=12306','root','',[PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION]);
  • query.php(查询余票):

    <?phprequire'db.php';$trainId=$_GET['train_id'];$stmt=$pdo->prepare(" SELECT COUNT(*) as available FROM seats WHERE train_id = ? AND status = 0 ");$stmt->execute([$trainId]);echojson_encode($stmt->fetch());
  • lock.php(锁定座位):

    <?phprequire'db.php';$trainId=$_POST['train_id'];// 乐观锁:仅锁定可用座位$pdo->beginTransaction();try{$stmt=$pdo->prepare(" SELECT id FROM seats WHERE train_id = ? AND status = 0 LIMIT 1 FOR UPDATE ");$stmt->execute([$trainId]);$seat=$stmt->fetch();if(!$seat){thrownewException('No seats available');}// 锁定座位$pdo->prepare("UPDATE seats SET status = 1 WHERE id = ?")->execute([$seat['id']]);// 创建订单$orderId=uniqid();$pdo->prepare(" INSERT INTO orders (id, user_id, train_id, seat_id) VALUES (?, 1, ?, ?) ")->execute([$orderId,$trainId,$seat['id']]);$pdo->commit();echojson_encode(['order_id'=>$orderId]);}catch(Exception$e){$pdo->rollback();http_response_code(400);echojson_encode(['error'=>$e->getMessage()]);}

三、阶段 2:核心功能增强(3 天)

▶ 1.余票缓存(防超卖)
  • 问题
    • 高并发下SELECT ... FOR UPDATE性能差
  • 解决方案
    -- 新增余票计数表CREATETABLEtrain_inventory(train_idINTPRIMARYKEY,available_seatsINTNOTNULL,versionINTDEFAULT0-- 乐观锁版本号);
  • 锁定逻辑
    // 先扣减库存$stmt=$pdo->prepare(" UPDATE train_inventory SET available_seats = available_seats - 1, version = version + 1 WHERE train_id = ? AND available_seats > 0 ");if($stmt->execute([$trainId])&&$stmt->rowCount()>0){// 再分配具体座位// ...}
▶ 2.订单超时释放
  • 方案
    • 定时任务扫描 15 分钟未支付订单
    • 释放座位并回滚库存
  • crontab
    */5 * * * * php /path/to/release_expired_orders.php
▶ 3.基础安全防护
  • SQL 注入
    • 全程使用PDO::prepare()
  • XSS
    • 输出时htmlspecialchars()
  • CSRF
    • 表单添加隐藏 Token 字段

四、阶段 3:性能与扩展(7 天+)

▶ 1.引入 Redis 缓存
  • 缓存余票
    // 查询余票$available=$redis->get("train:{$trainId}:seats");if($available===false){// 从 DB 加载并缓存$available=getFromDB();$redis->setex("train:{$trainId}:seats",30,$available);}
▶ 2.队列解耦(Swoole)
  • 架构

    提交订单

    Web 服务器

    Swoole 队列

    订单处理 Worker

    MySQL

  • 优势
    • Web 层快速响应
    • 异步处理高耗时操作
▶ 3.分库分表(未来扩展)
  • 拆分策略
    • 按车次日期分表(orders_20231001
    • 按用户 ID 分库

五、避坑指南

陷阱破局方案
直接实现分布式事务先用本地事务 + 补偿机制
过度设计缓存余票缓存足够,避免复杂多级缓存
忽略数据一致性FOR UPDATE或 Redis Lua 脚本保证原子性

六、终极心法

**“12306 不是系统,
而是领域的显影——

  • 当你建模实体
    你在校准边界;
  • 当你简化并发
    你在聚焦核心;
  • 当你渐进扩展
    你在铸造韧性。

真正的工程能力,
始于对领域的敬畏,
成于对细节的精控。”


结语

从今天起:

  1. 先实现单机版余票查询 + 锁定
  2. FOR UPDATE保证基础一致性
  3. 逐步引入 Redis/Swoole 优化

因为最好的高并发系统,
不是一蹴而就,
而是亲手活出每一行代码的密度。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 9:22:32

MedGemma X-Ray真实作品分享:10例典型胸部X光AI解读报告

MedGemma X-Ray真实作品分享&#xff1a;10例典型胸部X光AI解读报告 1. 这不是“AI看片”&#xff0c;而是能陪你一起思考的影像助手 你有没有试过盯着一张胸部X光片&#xff0c;反复比对肋骨走向、肺纹理分布、心影轮廓&#xff0c;却仍不确定某处模糊影是不是早期渗出&…

作者头像 李华
网站建设 2026/6/10 9:26:53

MedGemma-X保姆级教程:快速实现医学影像的智能识别与报告生成

MedGemma-X保姆级教程&#xff1a;快速实现医学影像的智能识别与报告生成 1. 为什么你需要这个“会说话的放射科助手” 你有没有遇到过这样的场景&#xff1a;一张刚拍完的胸部X光片摆在面前&#xff0c;要花5分钟确认肺纹理是否对称、肋膈角是否锐利、纵隔有无偏移&#xff…

作者头像 李华
网站建设 2026/6/10 9:25:03

2026年AI艺术创作入门必看:AI印象派艺术工坊+OpenCV算法实战指南

2026年AI艺术创作入门必看&#xff1a;AI印象派艺术工坊OpenCV算法实战指南 1. 为什么说这是小白最友好的AI艺术入门方式&#xff1f; 你是不是也试过那些动辄要下载几个GB模型、配环境像解谜、跑起来还报错十几次的AI绘画工具&#xff1f; 是不是每次看到“一键生成梵高风格…

作者头像 李华
网站建设 2026/6/10 9:24:36

Clawdbot+Qwen3:32B高效部署:GPU算力适配与Ollama本地模型加载优化

ClawdbotQwen3:32B高效部署&#xff1a;GPU算力适配与Ollama本地模型加载优化 1. 为什么需要Clawdbot来管理Qwen3:32B这类大模型 你有没有遇到过这样的情况&#xff1a;好不容易在本地跑起了Qwen3:32B&#xff0c;结果每次调用都要改一堆配置、换不同端口、手动启动服务&…

作者头像 李华
网站建设 2026/6/10 12:39:35

通义千问3-Reranker-0.6B开源部署:模型文件校验脚本+SHA256完整性验证

通义千问3-Reranker-0.6B开源部署&#xff1a;模型文件校验脚本SHA256完整性验证 1. 为什么你需要校验这个模型 你刚下载完 Qwen3-Reranker-0.6B&#xff0c;解压后发现文件夹里有十几个 .safetensors 文件和 config.json、model.safetensors.index.json 等一堆文件——但心里…

作者头像 李华
网站建设 2026/6/9 22:19:23

rs232串口调试工具数据帧解析错误排查方法

以下是对您提供的博文内容进行 深度润色与结构重构后的技术文章 。我以一位资深嵌入式系统工程师兼教学博主的身份,彻底摒弃模板化表达、AI腔调和教科书式罗列,转而采用 真实开发场景切入 + 问题驱动叙述 + 经验沉淀式讲解 的方式重写全文。语言更贴近一线工程师的思考节…

作者头像 李华