支付系统基本稳定了,下一个目标是搭建一套商城系统。不是要造淘宝,而是做一个能跑通完整电商流程的中小型系统,既是练手也是真要用。这篇先把架构理清楚。
为什么要自己做
市面上开源商城不少(mall、litemall等),但:
- 大部分是Java单体,我想用Go练手
- 很多开源项目代码质量参差不齐,二次开发成本不低
- 自己做一遍才能真正理解电商系统的复杂度
目标:一个人能维护的、功能完整的电商系统。不追求高并发(先跑通再说),但架构上要留好扩展空间。
领域模型
电商系统的核心领域:
商品域
- SPU(Standard Product Unit):标准产品单元,比如"iPhone 15"
- SKU(Stock Keeping Unit):库存量单位,比如"iPhone 15 蓝色 256G"
- 商品分类(多级)、品牌、商品属性(规格参数)
- 商品图片、详情(富文本)
订单域
- 订单(Order) -> 订单项(OrderItem)
- 订单状态机:待付款 -> 已付款 -> 已发货 -> 已收货 -> 已完成
- 取消、退款、售后是反向流程
- 订单号生成:时间戳+机器ID+序列号,确保全局唯一
支付域
- 已经做好了,直接对接上一个项目的支付网关
- 支付单和订单是一对一关系(简化处理,暂不支持合并支付)
库存域
- SKU维度的库存管理
- 下单时预扣库存(避免超卖),支付成功后确认扣减,超时未支付则释放
- 库存不做独立服务,放在商品服务里
用户域
- 注册/登录(手机号+验证码)
- 收货地址管理
- 用户等级(暂时简单做)
营销域
- 优惠券(满减、折扣)
- 限时特价
- 这块先留接口,后面慢慢加
微服务 vs 单体
一个人的项目,上微服务是自找麻烦吗?我的选择是模块化单体,为微服务做好准备。
具体来说:
- 代码按领域分模块,模块之间通过接口调用,不直接访问对方的数据库表
- 所有模块共享一个进程,部署简单
- 每个模块有自己的数据库schema(逻辑隔离)
- 如果后面某个模块需要独立扩展,拆出去改成gRPC调用就行
这个思路参考了Shopify早期的架构——他们也是从单体开始,随着业务增长逐步拆分。
技术选型
| 组件 | 选择 | 理由 |
|---|---|---|
| 语言 | Go 1.20 | 练手 + 部署简单 + 性能好 |
| Web框架 | Gin | 生态好,中间件丰富 |
| RPC | gRPC + protobuf | 为未来拆分准备 |
| 数据库 | PostgreSQL 15 | JSON字段存商品属性很方便 |
| 缓存 | Redis 7 | 会话、购物车、库存预扣 |
| 搜索 | Elasticsearch 8 | 商品搜索 |
| 消息队列 | Kafka | 订单事件、库存同步 |
| 对象存储 | MinIO | 商品图片,兼容S3 API |
| 容器 | Docker Compose | 本地开发一键启动 |
Go没有Spring那套成熟的生态,很多东西要自己组装。选Wire做依赖注入(下篇会写)。ORM用sqlc——直接写SQL,编译时生成Go代码,比GORM靠谱。
核心架构
+----------------+
| Nginx |
| (反向代理) |
+-------+--------+
|
+-------------+-------------+
| |
+--------v--------+ +------------v----------+
| 商城前端(Vue3) | | 管理后台(Vue3) |
+--------+---------+ +------------+----------+
| |
+-------------+-------------+
|
+-------v--------+
| API网关 |
| (Gin路由) |
+-------+--------+
|
+-------------------+-------------------+
| | |
+-----v-----+ +-------v-------+ +-------v-------+
| 商品模块 | | 订单模块 | | 用户模块 |
| Product | | Order | | User |
+-----+-----+ +-------+-------+ +-------+-------+
| | |
| +------v-------+ |
| | 支付模块 | |
| | Payment | |
| +--------------+ |
| |
+-----v---------------------------------------v------+
| PostgreSQL (schema隔离) |
+----+----------+----------+-----------+-------------+
| product | order | payment | user |
+----------+----------+-----------+------------------+
数据库设计要点
- 金额全部用BIGINT存储(单位:分),不用DECIMAL避免浮点问题
- 商品属性用PostgreSQL的JSONB字段,查询灵活
- 订单表做分表预留:订单号包含时间信息,后续按月分表
- 所有表加
created_at、updated_at、deleted_at(软删除)
项目结构
mall/
├── cmd/
│ └── server/ # 入口
├── internal/
│ ├── product/ # 商品模块
│ │ ├── handler/ # HTTP handler
│ │ ├── service/ # 业务逻辑
│ │ ├── repo/ # 数据访问
│ │ └── model/ # 数据模型
│ ├── order/ # 订单模块
│ ├── payment/ # 支付模块
│ ├── user/ # 用户模块
│ └── marketing/ # 营销模块(预留)
├── pkg/
│ ├── middleware/ # 通用中间件
│ ├── auth/ # JWT认证
│ └── response/ # 统一响应格式
├── api/
│ └── proto/ # protobuf定义
├── configs/
├── migrations/ # 数据库迁移
├── docker-compose.yml
└── Makefile
开发计划
- 第一阶段(2周):项目骨架搭建,用户注册登录,商品CRUD
- 第二阶段(2周):购物车、下单流程、库存扣减
- 第三阶段(1周):对接支付系统,完成支付流程
- 第四阶段(2周):商品搜索(ES)、前端页面
- 第五阶段(持续):营销功能、性能优化
先做后端API,前端用Vue3 + Element Plus快速搭。
下一篇先把Go的依赖注入搞定(Wire),这是整个项目的基础设施。