核心内容摘要
Isotonitazene NHS Ester,依替氮卓 琥珀酰亚胺酯在生物偶联中的应用进展
12306 的本质是高并发、强一致性、分布式事务的票务系统。
核心认知12306 的本质是什么▶
业务本质核心实体车次Train座位Seat订单Order核心流程查询余票锁定座位支付生成电子票▶
技术挑战挑战初学者简化方案高并发单机 MySQL 乐观锁分布式事务本地事务 补偿机制余票计算预分配座位池核心原则先实现单机版再考虑分布式
阶段 1单机 MVP1 天▶
数据库设计-- 车次表CREATETABLEtrains(idINTPRIMARYKEYAUTO_INCREMENT,train_noVARCHAR(
NOTNULL,-- G1234departureVARCHAR(
NOTNULL,-- 北京南arrivalVARCHAR(
NOTNULL,-- 上海虹桥depart_timeDATETIMENOTNULL);-- 座位表预分配CREATETABLEseats(idINTPRIMARYKEYAUTO_INCREMENT,train_idINTNOTNULL,seat_noVARCHAR(
NOTNULL,-- 05车12AstatusTINYINTDEFAULT0,-- 0可用, 1已锁定, 2已售FOREIGNKEY(train_id)REFERENCEStrains(id));-- 订单表CREATETABLEorders(idVARCHAR(
PRIMARYKEY,-- UUIDuser_idINTNOTNULL,train_idINTNOTNULL,seat_idINTNOTNULL,statusTINYINTDEFAULT0,-- 0待支付, 1已支付created_atDATETIMEDEFAULTCURRENT_TIMESTAMP,FOREIGNKEY(seat_id)REFERENCESseats(id));▶
PHP 基础代码无框架db.php数据库连接?php$pdonewPDO(mysql:hostlocalhost;dbname12306,root,,[PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION]);query.php查询余票?phprequiredb.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锁定座位?phprequiredb.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]]);// 创建订单$orderIduniqid();$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(
;echojson_encode([error$e-getMessage()]);}
阶段 2核心功能增强3 天▶
余票缓存防超卖问题高并发下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()
{// 再分配具体座位// ...}▶
订单超时释放方案定时任务扫描 15 分钟未支付订单释放座位并回滚库存crontab*/5 * * * * php /path/to/release_expired_orders.php▶
基础安全防护SQL 注入全程使用PDO::prepare()XSS输出时htmlspecialchars()CSRF表单添加隐藏 Token 字段
阶段 3性能与扩展7 天▶
引入 Redis 缓存缓存余票// 查询余票$available$redis-get(train:{$trainId}:seats);if($availablefalse){// 从 DB 加载并缓存$availablegetFromDB();$redis-setex(train:{$trainId}:seats,30,$available);}▶
队列解耦Swoole架构提交订单Web 服务器Swoole 队列订单处理 WorkerMySQL优势Web 层快速响应异步处理高耗时操作▶
分库分表未来扩展拆分策略按车次日期分表orders_20231001按用户 ID 分库
避坑指南陷阱破局方案直接实现分布式事务先用本地事务 补偿机制过度设计缓存余票缓存足够避免复杂多级缓存忽略数据一致性用FOR UPDATE或 Redis Lua 脚本保证原子性
终极心法**“12306 不是系统而是领域的显影——当你建模实体你在校准边界当你简化并发你在聚焦核心当你渐进扩展你在铸造韧性。
真正的工程能力始于对领域的敬畏成于对细节的精控。
”结语从今天起先实现单机版余票查询 锁定用FOR UPDATE保证基础一致性逐步引入 Redis/Swoole 优化因为最好的高并发系统不是一蹴而就而是亲手活出每一行代码的密度。