去年帮学校环保社团开发二手交易系统时,我深刻体会到校园闲置物品交易的痛点:学生群体交易频繁但缺乏保障,经常出现商品描述不符、付款后不发货等纠纷。这个用Python+Flask构建的平台,正是为了解决这些实际问题而生。
系统采用前后端分离架构,后端基于Flask轻量级框架提供RESTful API,前端使用Vue.js构建响应式界面,数据库选用MySQL+Redis组合。特别设计了信用评价体系和第三方支付托管,让校园二手交易像专业电商平台一样可靠。下面我将从技术选型到核心实现,详细拆解这个可落地的解决方案。
在技术选型阶段,我们对比了两种主流Python框架:
最终选择Flask主要考虑:
python复制# 典型Flask应用结构
app/
├── auth/ # 认证模块
│ ├── routes.py
│ └── models.py
├── goods/ # 商品模块
│ ├── views.py
│ └── services.py
└── __init__.py # 应用工厂
交易系统最核心的是数据一致性,我们的MySQL设计遵循:
| 状态码 | 含义 | 可操作 |
|---|---|---|
| 0 | 待支付 | 取消/支付 |
| 1 | 待发货 | 发货/申请退款 |
| 2 | 待收货 | 确认收货/申请售后 |
| 3 | 已完成 | 评价 |
| 4 | 已关闭 | - |
关键技巧:使用Redis缓存热门商品数据,将商品详情页QPS从150提升到1200+
信用分计算采用动态权重算法:
python复制def update_credit_score(user_id):
# 获取用户历史行为数据
deals = Deal.query.filter_by(buyer_id=user_id).count()
positive = Feedback.query.filter_by(to_user=user_id, score__gte=4).count()
negative = Feedback.query.filter_by(to_user=user_id, score__lt=2).count()
# 计算新信用分(基础分+正向激励-负向惩罚)
base = 80
deal_weight = min(deals * 0.1, 5) # 交易量加成上限5分
positive_weight = positive * 0.5 # 好评每单+0.5
negative_weight = negative * 1.2 # 差评每单-1.2
new_score = base + deal_weight + positive_weight - negative_weight
return max(min(round(new_score), 100), 0) # 限制在0-100区间
为解决"付款不发货"问题,我们引入第三方支付担保交易:
关键代码逻辑:
python复制@app.route('/pay/confirm', methods=['POST'])
def confirm_payment():
order = Order.query.get(request.json['order_id'])
if order.status != 0:
return jsonify({'error': '非法操作'}), 400
# 调用支付接口(示例用伪代码)
payment_result = third_party_pay(
amount=order.amount,
order_no=order.order_no,
callback_url=url_for('pay.callback', _external=True)
)
if payment_result['status'] == 'success':
order.status = 1 # 更新为待发货
db.session.commit()
return jsonify({'msg': '支付成功'})
else:
return jsonify({'error': payment_result['msg']}), 500
初期使用LIKE查询导致性能瓶颈(200ms+响应),优化后方案:
优化前后对比:
| 方案 | QPS | 平均响应 | 内存占用 |
|---|---|---|---|
| 原始LIKE | 32 | 210ms | 120MB |
| 全文索引 | 150 | 45ms | 160MB |
| 分词+缓存 | 480 | 18ms | 220MB |
用户上传图片遇到两个典型问题:
解决方案:
python复制from PIL import Image
from io import BytesIO
def process_image(file_stream, max_size=800):
"""处理上传图片:调整尺寸+压缩"""
img = Image.open(BytesIO(file_stream))
# 等比例缩放
width, height = img.size
if max(width, height) > max_size:
ratio = max_size / max(width, height)
new_size = (int(width*ratio), int(height*ratio))
img = img.resize(new_size, Image.LANCZOS)
# 质量压缩
output = BytesIO()
img.save(output, format='JPEG', quality=85, optimize=True)
return output.getvalue()
实测效果:图片体积平均减少70%,页面加载速度提升3倍
根据校园场景特点,推荐配置:
使用Prometheus+Granfana监控关键指标:
配置示例(prometheus.yml):
yaml复制scrape_configs:
- job_name: 'flask_app'
metrics_path: '/metrics'
static_configs:
- targets: ['app-server:5000']
- job_name: 'mysql'
static_configs:
- targets: ['db-server:9104']
现象:支付成功后订单状态未更新
排查步骤:
根本原因:支付平台重试机制导致重复回调
解决方案:增加幂等处理
python复制@app.route('/pay/callback', methods=['POST'])
def payment_callback():
order = Order.query.get(request.json['order_no'])
if order.status != 0: # 已处理过的订单直接返回成功
return jsonify({'status': 'success'})
...
现象:超卖现象
解决方案:使用SELECT FOR UPDATE锁
python复制def reduce_stock(item_id, count):
with db.session.begin():
item = Goods.query.with_for_update().get(item_id)
if item.stock >= count:
item.stock -= count
else:
raise ValueError("库存不足")
在实际运行半年后,我们总结了三个有价值的扩展点:
这个项目让我深刻体会到:好的校园系统不需要多高大上,关键是解决真实场景中的具体问题。现在每次在食堂看到同学通过这个平台交易教材,都比收到任何技术赞誉更有成就感。