news 2026/3/14 2:53:22

零基础从零到一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/3/13 8:50:20

零基础玩转QAnything PDF解析:从安装到实战

零基础玩转QAnything PDF解析&#xff1a;从安装到实战 你是不是也遇到过这些情况&#xff1a; 手头有一份几十页的PDF技术文档&#xff0c;想快速提取关键内容却只能一页页手动复制&#xff1f; 扫描版PDF里的表格和图片文字看不清&#xff0c;复制出来全是乱码&#xff1f; …

作者头像 李华
网站建设 2026/3/10 21:57:42

vue+uniapp+python校园头条新闻小程序--带爬虫

文章目录 技术栈说明爬虫模块实现前端实现&#xff08;UniAppVue&#xff09;后端API设计&#xff08;Python示例&#xff09;部署与上线注意事项 系统设计与实现的思路主要技术与实现手段源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; …

作者头像 李华
网站建设 2026/3/10 1:26:00

MedGemma X-Ray企业级应用:集成至PACS前置分析模块的技术可行性验证

MedGemma X-Ray企业级应用&#xff1a;集成至PACS前置分析模块的技术可行性验证 1. 引言&#xff1a;当AI阅片助手走进临床工作流 你有没有想过&#xff0c;一张刚拍完的胸部X光片&#xff0c;在进入放射科医生视野前&#xff0c;就能自动完成初步结构识别、关键异常标记和结…

作者头像 李华
网站建设 2026/3/13 21:03:47

Clawdbot+Qwen3-32B实战指南:Web聊天平台日志记录、审计与导出功能

ClawdbotQwen3-32B实战指南&#xff1a;Web聊天平台日志记录、审计与导出功能 1. 为什么需要日志记录与审计能力 你有没有遇到过这样的情况&#xff1a;用户反馈“刚才机器人回答错了”&#xff0c;但你打开后台却找不到那条对话&#xff1b;或者团队想复盘某次客服响应质量&…

作者头像 李华
网站建设 2026/3/12 19:15:34

Qwen3-Embedding-4B入门必看:语义搜索准确率与知识库密度关系分析

Qwen3-Embedding-4B入门必看&#xff1a;语义搜索准确率与知识库密度关系分析 1. 什么是Qwen3-Embedding-4B语义搜索&#xff1f; 你有没有遇到过这样的问题&#xff1a;在知识库中搜“怎么让PPT动起来”&#xff0c;结果返回的全是“PowerPoint动画设置步骤”&#xff0c;但…

作者头像 李华