我们可以从“历史演进”和“当前核心架构”两个维度来理解它。

(图片来源网络,侵删)
历史演进:从“崩溃”到“坚不可摧”
12306的架构经历了几个关键阶段,每个阶段都是为了解决当时最棘手的问题。
初期阶段(约2011-2012年):单体架构 + 数据库瓶颈
- 架构特点:典型的单体应用,所有功能(用户、订单、车票、支付)都耦合在一个巨大的Java应用中,数据库使用传统的Oracle + RAC (Real Application Clusters) 集群。
- 核心问题:
- 数据库是最大瓶颈:所有请求最终都要查询和更新数据库,尤其是在春运期间,瞬时巨大的查询请求直接冲垮了数据库,导致系统雪崩。
- 扩展性差:单体应用无法水平扩展,只能通过增加应用服务器数量,但核心数据库的压力无法缓解。
- 用户体验极差:著名的“排队”和“系统繁忙”页面,就是数据库无法响应的直接体现。
第一次重大演进:引入缓存与读写分离
- 架构特点:
- 引入缓存:在应用和数据库之间加入了Redis等内存数据库,将热点数据(如车次信息、余票信息)缓存起来,极大减轻了数据库的读压力。
- 读写分离:将数据库拆分为一个主库(Master)和多个从库(Slave),写操作(如购票)走主库,读操作(如查余票)走从库。
- 核心问题:
- 缓存穿透/击穿/雪崩:虽然引入了缓存,但在极端高并发下,缓存数据失效或大量请求直接绕过缓存,依然可能导致数据库崩溃。
- 数据一致性问题:缓存和数据库的数据同步存在延迟,可能导致用户看到有余票但点击后提示“已售罄”的情况。
第二次重大演进:服务化与分布式架构
- 架构特点:将庞大的单体应用拆分成多个独立的微服务。
- 用户服务:负责用户注册、登录、个人信息管理。
- 车次服务:负责车次、站点信息的发布和管理。
- 订单服务:负责订单的创建、支付、状态变更。
- 票务服务:负责余票查询、锁票、出票等核心业务。
- 支付服务:对接第三方支付平台。
- 技术选型:引入了Dubbo作为服务治理框架,用于服务间的发现、调用和负载均衡。
- 核心优势:
- 解耦:各服务独立开发、部署和扩展,一个服务的故障不会直接导致整个系统崩溃。
- 弹性伸缩:可以根据流量,对“票务服务”这类核心服务进行独立扩容,而其他服务则保持较小的规模。
第三次重大演进:引入云原生与消息队列
- 架构特点:这是12306架构成熟的关键一步,全面拥抱云原生技术。
- 消息队列:引入Kafka等消息队列,购票流程不再是同步的“下单-锁票-支付”,而是变成了异步的“下单 -> 发送消息 -> 消费消息完成锁票”。
- 削峰填谷:将瞬时高并发请求缓冲到消息队列中,后端的票务服务按自己的处理能力消费消息,避免了流量洪峰直接冲击核心业务。
- 系统解耦:订单服务和票务服务通过消息队列解耦,提高了系统的稳定性和容错能力。
- 容器化与编排:全面采用Docker进行应用打包,并使用Kubernetes (K8s) 进行容器编排和自动化管理,实现了应用的快速部署、弹性伸缩和故障自愈。
- 多级缓存:构建了从浏览器到应用再到数据库的多级缓存体系,如CDN、浏览器缓存、Nginx缓存、应用缓存、Redis缓存等,最大限度减少对数据库的访问。
- 消息队列:引入Kafka等消息队列,购票流程不再是同步的“下单-锁票-支付”,而是变成了异步的“下单 -> 发送消息 -> 消费消息完成锁票”。
当前核心架构(深度解析)
现在的12306架构是一个高度复杂、多层分级的分布式系统,我们可以将其从上到下分为几个层次:
用户接入层
这是用户访问的第一道关口,目标是高效、安全地接收海量用户请求。
- CDN (Content Delivery Network):缓存静态资源(如JS、CSS、图片)和部分动态页面(如首页、车次列表),将内容推离用户最近的节点,加速访问,并减轻源站压力。
- 负载均衡:通过SLB (Server Load Balancer) 或 F5 硬件设备,将海量的用户请求均匀分发到后端的多个Web服务器集群。
- WAF (Web Application Firewall):防护SQL注入、XSS等网络攻击,保障系统安全。
应用服务层
这是业务逻辑的核心执行层,由多个独立的微服务集群组成。

(图片来源网络,侵删)
- 技术栈:基于Java开发,运行在Kubernetes管理的容器集群中。
- 核心服务:
- 前端服务:负责渲染页面,调用后端API。
- 用户服务:处理用户认证、授权、个人信息。
- 车次服务:提供车次、席别、站点等基础数据查询。
- 订单服务:处理订单的创建、状态流转、取消等。
- 票务服务:最核心的服务,处理余票查询、锁票、出票逻辑,为了保证高性能,这部分逻辑通常非常精简。
- 支付服务:对接支付宝、微信支付等渠道。
- 特点:
- 无状态设计:服务实例本身不保存用户状态,所有状态存储在外部(如Redis、数据库),方便水平扩展。
- 弹性伸缩:K8s根据实时流量自动增减服务实例的数量,例如在开售高峰瞬间启动大量实例,售完后自动缩减。
数据存储层
这是系统的数据基石,采用了多种数据库和技术,以满足不同场景的需求。
- 关系型数据库:
- 主库:处理写操作(如创建订单、锁票),为了保证数据强一致性和可靠性,仍然可能使用Oracle或MySQL集群,并配有主从复制和异地灾备方案。
- 从库:处理读操作(如查余票、查订单),分担主库压力。
- NoSQL数据库:
- Redis:作为核心缓存,缓存车次信息、余票信息、用户Session等,这是整个系统性能的关键。
- MongoDB/HBase:可能用于存储非结构化或半结构化数据,如日志、用户行为分析等。
- 分布式数据库:
对于海量的订单数据,可能会采用分布式数据库(如TiDB)进行分片存储,以突破单机数据库的性能和容量瓶颈。
- 文件存储:
使用对象存储(如阿里云OSS)来存储用户身份证、车票图片等文件。
消息中间件层
这是系统高可用的“缓冲垫”和“解耦器”。

(图片来源网络,侵删)
- 核心组件:Kafka 或 RocketMQ。
- 核心作用:
- 异步处理:将“下单-锁票”这个关键流程解耦,用户下单后,订单服务只需向Kafka发送一条“订单创建”的消息,然后立即返回“下单成功”,后续的锁票、出票操作由票务服务作为消费者异步从Kafka中获取消息并执行。
- 削峰填谷:在春运开售瞬间,会有数百万请求涌入,Kafka作为巨大的缓冲池,将这些请求暂存起来,后端的票务服务可以以稳定的速率消费,避免系统被冲垮。
- 系统解耦与容错:如果票务服务暂时不可用,订单不会失败,消息会保留在Kafka中,待服务恢复后继续处理,保证了系统的最终一致性。
核心技术与创新点
除了上述分层架构,12306还运用了一些独特的技术来应对极端挑战。
- 分布式事务:如何保证“下单-锁票-支付”全流程的数据一致性?12306采用了最终一致性方案,结合消息队列和本地事务,确保即使某个环节失败,数据最终也能达到一致状态。
- 分布式锁:在并发锁票时,如何防止多个用户同时锁同一张票?使用Redis的
SETNX(SET if Not eXists) 命令实现分布式锁,确保锁票操作的原子性。 - 高可用与异地多活:
- 多机房部署:核心服务在多个物理数据中心部署,当一个机房出现故障时,流量可以自动切换到其他机房。
- 数据同步:跨机房的数据通过专线和复制技术保持同步,实现业务层面的“多活”。
- 流量调度与风控:
- 流量整形:通过API网关对请求进行限流、熔断,防止恶意请求或异常流量。
- 智能风控:利用大数据和机器学习技术,识别黄牛、刷票等异常行为,并进行拦截。
12306的技术架构是一个典型的“分层解耦、异步化、缓存优先、弹性伸缩”的现代化分布式系统。
- 从单体到微服务:实现了系统解耦和独立扩展。
- 从同步到异步:通过消息队列解决了高并发下的系统稳定性和性能问题。
- 从缓存到多级缓存:最大限度地减少了对数据库的访问,是性能提升的关键。
- 从物理机到云原生:通过K8s实现了极致的自动化运维和弹性伸缩能力。
12306的成功,不仅是中国工程师智慧和汗水的结晶,也为全球范围内处理超大规模高并发业务提供了宝贵的实践范例,它证明了在正确的技术架构和持续的工程优化下,即使是像春运这样看似不可能完成的任务,也能够被稳定、高效地完成。
