1. 项目背景与核心需求
电影院网上订票系统是现代影院运营的刚需功能。随着移动互联网普及,超过70%的观众选择通过手机APP完成购票。这个基于SSM框架和Android平台的订票系统,主要解决传统线下购票的三大痛点:
- 排队时间长:热门场次线下购票平均等待超过15分钟
- 座位信息不透明:观众无法实时查看可选座位分布
- 支付方式单一:多数影院仅支持现金或刷卡
系统采用B/S与C/S混合架构:后台使用SSM(Spring+SpringMVC+MyBatis)框架提供RESTful API,前端Android应用通过HTTPS协议与后台交互。这种架构既保证了后台的高可用性,又充分发挥了移动端的用户体验优势。
实际开发中发现:影院业务存在明显的时段性高峰,系统设计必须考虑秒级并发处理能力。我们通过Redis缓存热点数据和分布式Session解决了这个问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术栈选型与架构设计
2.1 后端技术栈
SSM框架组合经过多年企业级开发验证,是本系统的最佳选择:
- Spring 5.3:IoC容器管理影院、排片等业务Bean
- SpringMVC:处理Android端REST请求,响应时间控制在200ms内
- MyBatis 3.5:通过动态SQL优化复杂查询,如多条件筛选场次
数据库采用MySQL 8.0+InnoDB集群,主从复制保证高可用。关键表设计示例:
sql复制CREATE TABLE `t_schedule` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`movie_id` BIGINT NOT NULL COMMENT '影片ID',
`hall_id` INT NOT NULL COMMENT '影厅ID',
`start_time` DATETIME NOT NULL COMMENT '开场时间',
`price` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
`remain_seats` INT NOT NULL COMMENT '剩余座位数',
KEY `idx_movie` (`movie_id`),
KEY `idx_time` (`start_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2 移动端关键技术
Android端采用MVP模式分层开发,核心模块包括:
- 网络通信层:Retrofit2+OkHttp3实现API调用
- 数据持久层:Room数据库缓存常用数据
- UI渲染层:使用RecyclerView实现座位矩阵选择
支付模块集成支付宝和微信SDK时需特别注意:
java复制// 微信支付初始化
IWXAPI api = WXAPIFactory.createWXAPI(this, "APP_ID");
api.registerApp("APP_ID");
// 支付宝参数组装
final String orderInfo = new PayTask(this).payInfo(
orderId, price, "电影票", "观影消费");
3. 核心功能实现细节
3.1 实时座位锁定机制
为避免并发选座冲突,采用Redis分布式锁实现:
- 用户选择座位时,执行
SETNX lock:seat_{id} {userId} EX 300 - 操作完成或超时后,通过Lua脚本保证原子性释放:
lua复制if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
实测数据显示,该方案比数据库行锁性能提升20倍,在2000并发请求下平均响应时间保持在150ms以内。
3.2 订单状态机设计
订单流程包含复杂状态转换,我们采用状态模式实现:
java复制public interface OrderState {
void pay(Order order);
void cancel(Order order);
void complete(Order order);
}
// 具体状态实现
public class UnpaidState implements OrderState {
@Override
public void pay(Order order) {
// 扣款逻辑
order.setState(new PaidState());
}
}
状态转换触发持久化操作,通过MyBatis的@UpdateProvider动态生成SQL,减少数据库压力。
4. 性能优化实战经验
4.1 高并发场次查询
热门影片首映时,场次查询接口QPS可能突破5000。我们采用多级缓存策略:
- 本地缓存:Caffeine缓存影厅基础信息(有效期5分钟)
- 分布式缓存:Redis存储实时座位数据(秒级更新)
- 数据库:仅用于最终一致性校验
缓存更新通过RabbitMQ消息队列异步处理,核心配置:
yaml复制spring:
redis:
host: redis-cluster
timeout: 3000
rabbitmq:
addresses: mq1:5672,mq2:5672
publisher-confirms: true
4.2 Android端启动优化
通过Android Studio的Profiler工具分析发现:
- 首页加载耗时主要在网络请求和图片解码
- 启动时间从2.1s优化到0.8s的关键步骤:
- 使用
<merge>标签减少布局层级 - 预加载网络数据:在SplashScreen初始化Retrofit
- 图片处理:Glide开启磁盘缓存
kotlin复制Glide.with(this)
.load(movie.posterUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(binding.ivPoster)
5. 典型问题排查实录
5.1 座位图渲染卡顿
现象:滚动包含100+座位的RecyclerView时出现明显掉帧
排查过程:
- 使用Android GPU Inspector检查:每帧耗时超过16ms
- 发现自定义SeatView的
onDraw()中有复杂计算 - 优化方案:
- 预计算座位坐标并缓存
- 使用
Canvas.drawBitmap替代矢量绘制 - 启用RecyclerView的
setItemViewCacheSize
优化后FPS从45提升到稳定的60,内存占用减少30%。
5.2 支付状态同步延迟
线上曾出现:用户完成支付但订单状态未更新。通过日志分析:
- 微信支付回调接口平均响应时间达1.2秒
- 数据库监控显示回调期间有锁等待
- 解决方案:
- 将状态更新改为异步队列处理
- 增加前端轮询机制(间隔5秒)
- 添加补偿任务定时核对支付平台
最终状态同步延迟从最高15分钟降低到10秒内。
6. 安全防护方案
6.1 防刷票机制
针对黄牛刷票行为,实施多维度防护:
- 行为分析:同一IP/设备在10分钟内超过5次下单触发验证码
- 业务限制:热门场次单个账号最多购买4张票
- 机器学习:通过历史数据识别异常购买模式
核心代码片段:
java复制@RateLimiter(value = 5, key = "#userId")
public Order createOrder(Long userId, Schedule schedule) {
// 业务逻辑
}
6.2 数据加密方案
敏感数据传输采用HTTPS+自定义加密:
- 关键参数(如金额、座位号)使用AES加密
- 签名验证防止参数篡改:
java复制String sign = DigestUtils.md5Hex(
orderId + price + timestamp + SECRET_KEY);
在Android端,将密钥存储在Native层(C++),增加反编译难度。
7. 测试与部署策略
7.1 压力测试方案
使用JMeter模拟真实场景:
- 测试场景:周末晚间黄金时段
- 并发模型:500用户阶梯式增加
- 关键指标:
- 订单接口成功率 >99.99%
- 95%响应时间 <1秒
测试结果:
code复制| 并发数 | 平均响应时间 | 错误率 |
|--------|--------------|--------|
| 200 | 320ms | 0% |
| 500 | 680ms | 0.2% |
7.2 持续交付流水线
基于Jenkins搭建CI/CD:
- 代码提交触发单元测试(覆盖率>80%)
- 静态代码分析:SonarQube检测关键问题
- 自动化部署到K8s集群:
bash复制kubectl rollout restart deployment/cinema-backend
通过ArgoCD实现蓝绿部署,确保升级过程零停机。
