1. 项目背景与需求分析
高校食堂作为师生日常就餐的主要场所,传统管理模式面临着诸多痛点:用餐高峰期排队拥挤、人工结算效率低下、菜品供需匹配不精准、运营数据统计滞后等。我在参与某高校食堂信息化改造项目时,亲身体验到这些问题的严重性——午餐时段平均排队时间长达25分钟,菜品浪费率高达18%,而学生对菜品质量的反馈渠道几乎为零。
基于这些实际痛点,我们决定开发一套融合Django和Flask优势的餐饮管理系统。Django作为全功能框架,其自带的Admin后台、完善的ORM和认证系统非常适合快速构建管理模块;而Flask的轻量级特性则便于实现灵活的微服务接口。这种组合既能保证开发效率,又能满足高校食堂场景下的特殊需求。
2. 技术架构设计
2.1 混合框架选型策略
在技术选型阶段,我们对比了三种方案:
- 纯Django方案:开发效率高但灵活性不足
- 纯Flask方案:灵活性好但重复造轮子
- Django+Flask混合方案:兼顾效率与灵活
最终选择混合架构的核心考量是:
- Django处理核心业务逻辑(用户管理、订单处理)
- Flask实现需要快速迭代的功能(评价系统、数据分析API)
- 两者共享同一个MySQL数据库,通过数据库级联确保数据一致性
2.2 数据库设计要点
考虑到高校食堂日均订单量在3000-5000笔左右,我们采用分表策略:
python复制# Django模型示例
class Dish(models.Model):
canteen = models.ForeignKey(Canteen, on_delete=models.CASCADE) # 食堂分片键
name = models.CharField(max_length=50)
price = models.DecimalField(max_digits=6, decimal_places=2)
# 其他字段...
# Flask-SQLAlchemy模型
class OrderDetail(db.Model):
__bind_key__ = 'order_db' # 分库配置
dish_id = db.Column(db.Integer, db.ForeignKey('dish.id'))
quantity = db.Column(db.Integer)
关键设计决策:
- 按食堂分片存储菜品数据
- 订单明细单独分库
- 使用Redis缓存热门菜品数据(TTL设置15分钟)
3. 核心模块实现
3.1 智能预约系统
为解决排队问题,我们开发了动态预约算法:
python复制# Flask实现的预约容量计算
@app.route('/api/capacity', methods=['GET'])
def calculate_capacity():
current_hour = datetime.now().hour
base_capacity = 100 # 基础容量
# 获取最近3天同期数据
history_data = get_history_data(current_hour)
# 考虑天气因素
weather_factor = get_weather_factor()
# 动态调整
dynamic_capacity = base_capacity * (1 + history_data['avg_change']) * weather_factor
return jsonify({'capacity': int(dynamic_capacity)})
实测效果:
- 早餐时段排队时间减少62%
- 窗口利用率提升45%
3.2 支付对账机制
针对校园卡和移动支付的双渠道场景,我们设计了双重验证机制:
- 前端JS生成支付指纹(包含时间戳+用户ID+随机数)
- 支付网关回调时验证签名
- 每日凌晨跑对账任务(Celery定时任务)
python复制# Django中的对账任务
@shared_task
def daily_reconciliation():
from django.db import transaction
with transaction.atomic():
# 获取所有待对账记录
pending_payments = Payment.objects.filter(
status=Payment.PENDING
).select_for_update()
# 与支付平台核对
for payment in pending_payments:
gateway_status = check_gateway_status(payment.trade_no)
if gateway_status == 'SUCCESS':
payment.confirm_payment()
4. 性能优化实践
4.1 高并发场景处理
在12:00-12:30的极端高峰时段,我们采用三级缓存策略:
- 热点数据缓存在内存(如菜品库存)
- 频繁访问的API结果缓存Redis
- CDN缓存静态资源
Nginx配置示例:
nginx复制location /api/menu {
proxy_cache menu_cache;
proxy_cache_valid 200 5m;
proxy_pass http://backend;
}
4.2 数据库优化
通过EXPLAIN分析发现菜品查询的瓶颈后,我们进行了以下优化:
- 为canteen_id和category_id添加联合索引
- 将TEXT字段改为VARCHAR(255)
- 使用select_related减少查询次数
优化前后对比:
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 平均查询时间 | 320ms | 45ms |
| 峰值QPS | 120 | 450 |
5. 部署与监控
5.1 容器化部署方案
使用Docker Compose编排服务:
yaml复制version: '3'
services:
web:
image: ${DOCKER_REGISTRY}/canteen-web
ports:
- "8000:8000"
depends_on:
- redis
- mysql
celery:
image: ${DOCKER_REGISTRY}/canteen-worker
command: celery -A core worker -l info
redis:
image: redis:alpine
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
5.2 监控告警配置
Prometheus监控指标包括:
- 订单处理延迟
- 数据库连接池使用率
- API成功率
Grafana仪表盘设置关键阈值:
- 数据库连接数 >80% 触发告警
- 500错误率 >1% 触发告警
6. 踩坑经验总结
-
混合框架通信问题:
- 初期直接使用HTTP调用导致性能瓶颈
- 改用gRPC后性能提升3倍
- 关键配置:设置合理的keepalive时间
-
微信支付证书加载:
- 容器环境下路径问题导致加载失败
- 解决方案:将证书放在/etc/certs/固定路径
- 通过环境变量控制加载方式
-
库存超卖问题:
- 最初使用SELECT FOR UPDATE导致死锁
- 最终方案:Redis原子计数器+数据库最终一致
python复制def deduct_stock(dish_id, quantity): with redis.lock(f'dish_{dish_id}', timeout=5): current = redis.get(f'stock_{dish_id}') if current >= quantity: redis.decrby(f'stock_{dish_id}', quantity) async_update_db.delay(dish_id, quantity) return True return False -
时间戳混乱问题:
- 容器时区与数据库时区不一致
- 统一使用UTC时间存储
- 前端按用户时区显示
这个项目让我深刻体会到,高校信息化系统需要特别关注:
- 极端高峰时段的稳定性
- 多角色权限的精细控制
- 与校园现有系统的对接
- 学生使用习惯的培养
实际部署后最意外的收获是:通过数据分析发现,将畅销菜品窗口位置调整到取餐路线中段,可以分流15%的排队压力。这种数据驱动的优化方式,正是数字化管理的核心价值所在。