在电商系统开发中,我最终选择了Flask+Django的组合方案。这种混合架构的考虑在于:Django ORM和Admin非常适合快速搭建后台管理系统,而Flask的轻量级特性更适合高频交易接口。具体实施时,商品管理、用户中心等CRUD密集型模块使用Django,支付、订单等高性能接口采用Flask实现。
关键提示:Django REST Framework确实能快速生成API,但在实际压测中发现其默认配置的QPS比纯Flask低30%左右。建议在商品列表等高频接口使用Flask+SQLAlchemy原生查询优化。
UniApp的选择主要基于三点考量:首先是小程序生态的普及度,微信端用户占比超过60%;其次是开发效率,一套代码可编译到iOS/Android/Web三端;最后是Vue.js的技术栈统一,团队前端人员无需额外学习成本。实测中使用uView组件库,其内置的sku选择器组件节省了约40%的开发时间。
电商系统最复杂的莫过于商品模型设计。我们采用SPU(标准产品单元)+SKU(库存量单位)的分离结构:
python复制class SPU(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100)) # 商品标题
description = db.Column(db.Text) # 商品详情
category_id = db.Column(db.Integer) # 类目ID
class SKU(db.Model):
id = db.Column(db.Integer, primary_key=True)
spu_id = db.Column(db.Integer, db.ForeignKey('spu.id'))
price = db.Column(db.DECIMAL(10,2)) # 当前价格
stock = db.Column(db.Integer) # 库存
specs = db.Column(db.JSON) # 规格属性
这种设计的优势在于:
订单流程采用有限状态机(FSM)管理,这是避免订单状态混乱的关键。我们使用Python的transitions库实现:
python复制from transitions import Machine
class Order:
states = ['unpaid', 'paid', 'shipped', 'completed', 'cancelled']
def __init__(self):
self.machine = Machine(model=self, states=Order.states, initial='unpaid')
# 定义状态转换
self.machine.add_transition('pay', 'unpaid', 'paid')
self.machine.add_transition('ship', 'paid', 'shipped')
self.machine.add_transition('complete', 'shipped', 'completed')
self.machine.add_transition('cancel', '*', 'cancelled')
实际开发中需要特别注意:
电商系统最怕的就是超卖问题。我们对比了三种方案:
| 方案 | 实现复杂度 | 性能 | 一致性 | 适用场景 |
|---|---|---|---|---|
| 数据库乐观锁 | 低 | 中等 | 一般 | 低频抢购 |
| Redis原子计数器 | 中 | 高 | 强 | 秒杀活动 |
| 预扣库存+异步确认 | 高 | 极高 | 最终 | 大促期间 |
最终采用分级策略:普通商品用MySQL乐观锁,秒杀商品用Redis+Lua脚本:
lua复制-- inventory.lua
local key = KEYS[1]
local change = tonumber(ARGV[1])
local current = tonumber(redis.call('GET', key))
if current >= change then
return redis.call('DECRBY', key, change)
else
return -1
end
订单创建环节需要使用分布式锁防止重复提交。比较了三种实现方式:
最终选择Redis锁配合以下优化:
python复制def acquire_lock(conn, lockname, acquire_timeout=10):
identifier = str(uuid.uuid4())
end = time.time() + acquire_timeout
while time.time() < end:
if conn.setnx('lock:' + lockname, identifier):
conn.expire('lock:' + lockname, 10)
return identifier
elif not conn.ttl('lock:' + lockname):
conn.expire('lock:' + lockname, 10)
time.sleep(0.001)
return False
采用Docker Compose编排服务,典型配置如下:
yaml复制version: '3'
services:
web:
build: ./flask_app
ports:
- "5000:5000"
depends_on:
- redis
- mysql
redis:
image: redis:6
volumes:
- redis_data:/data
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
- mysql_data:/var/lib/mysql
volumes:
redis_data:
mysql_data:
关键优化点:
搭建Prometheus+Grafana监控看板,主要采集指标包括:
最坑的是微信支付异步通知,必须注意:
前端是uni-app,后端是Flask时,要特别注意:
javascript复制// uni-app manifest.json
"h5": {
"devServer": {
"proxy": {
"/api": {
"target": "http://localhost:5000",
"changeOrigin": true
}
}
}
}
商品图片上传遇到过内存溢出问题,解决方案:
nginx复制location /upload {
client_max_body_size 10M;
proxy_pass http://flask_app;
}
使用Vuex管理全局状态时,建议采用模块化设计:
javascript复制// store/modules/cart.js
export default {
state: () => ({
items: []
}),
mutations: {
ADD_ITEM(state, product) {
const existing = state.items.find(i => i.id === product.id)
existing ? existing.qty++ : state.items.push({...product, qty: 1})
}
}
}
需要注意:
通过以下手段将H5首屏加载时间从4s降到1.5s:
const Home = () => import('@/views/Home')XSS防护:
CSRF防护:
SQL注入:
敏感数据采用分层加密策略:
python复制from cryptography.fernet import Fernet
cipher_suite = Fernet(key)
encrypted_text = cipher_suite.encrypt(b"secret message")
decrypted_text = cipher_suite.decrypt(encrypted_text)
第一期上线后需要重点优化的技术债:
后续迭代可考虑的功能增强:
这个电商项目从技术选型到核心实现,每个环节都需要平衡开发效率与系统性能。最大的体会是:没有完美的架构,只有适合当前业务阶段的解决方案。比如初期直接用Django Admin快速搭建后台,等业务量上来后再逐步重构关键服务,这种渐进式优化比一开始就追求完美架构更务实。