多品类统一价格管理与计价系统设计:电商·虚拟商品·本地生活
一、背景与挑战
1.1 多品类价格差异
在数字电商/本地生活平台中,不同品类的定价逻辑差异极大:
| 品类 | 价格特点 | 定价维度 | 费用组成 | 典型示例 |
|---|---|---|---|---|
| 酒店 (Hotel) | 时间维度定价,每日价格独立 | 日期 × 房型 × 早餐 | 房价 + DP Fee + Hub Fee | 曼谷万豪豪华房 |
| 电影票 (Movie) | 场次 × 座位 × 票种定价 | 场次 × 座位区 × 票种 | 票价 + DP Fee + 选座费 | 阿凡达3 IMAX 成人票 |
| 话费充值 (TopUp) | 面额定价,无 SKU 变体 | 运营商 × 面额 | 面额 + 手续费 - 补贴 | AIS 100฿ 充值 |
| 电子券 (E-voucher) | 面值 vs 售价差异 | 品牌 × 面值 | 面值 - 平台折扣 + DP Fee | 星巴克 500฿ 电子券 |
| 礼品卡 (Giftcard) | 面值定价 + 平台折扣 | 品牌 × 面值 | 面值 - 折扣 + DP Fee | Google Play 充值卡 |
| 本地生活套餐 | 组合定价,子项加总 | 套餐 × 子项 × 份数 | 套餐价 + 服务费 | 海底捞双人套餐 |
1.2 核心痛点
- 价格散落多表:基础价、营销价、费用、优惠券分散在不同模块,缺乏统一视图。
- 计算逻辑分散:各品类各自实现价格计算,重复代码多,难以维护。
- 营销活动隔离:促销规则硬编码在业务逻辑中,扩展性差。
- Fee 管理混乱:DP Fee、Hub Fee、Carrier Fee 等多种费用缺乏统一配置。
- 优惠券叠加复杂:Voucher、Promo Code、积分抵扣等多种优惠方式叠加规则不清晰。
- 审计困难:价格变更历史难以追溯,用户投诉时无法准确还原计算过程。
- 精度与币种问题:多币种场景下精度不一致,浮点运算导致分摊误差。
1.3 设计目标
| 目标 | 说明 | 优先级 |
|---|---|---|
| 统一价格中心 | 所有价格计算通过统一的 Pricing Engine 进行 | P0 |
| 分层价格模型 | 基础价 → 营销价 → 费用 → 优惠券 → 最终价,层次清晰 | P0 |
| 规则引擎化 | 营销活动、费用规则可配置,支持动态调整 | P0 |
| 价格快照 | 每笔订单保留完整价格计算明细,支持审计和追溯 | P0 |
| 高性能 | P99 < 100ms,支持万级 QPS 并发价格计算 | P1 |
| 多级降级 | 促销/优惠券服务不可用时,仍能返回基础价格 | P1 |
| 可扩展 | 新增营销活动类型、费用类型、优惠券类型无需改动核心架构 | P1 |
二、整体架构
2.1 四层价格架构
1 | ┌─────────────────────────────────────────────────────────────────────┐ |
2.2 分层服务架构
1 | ┌──────────────────────────────────────────────────────────────────┐ |
2.3 价格组件定义
| 组件 | 说明 | 计算方式 | 示例 |
|---|---|---|---|
| Base Price | SKU 基础售价 | 固定 / 时间动态 | 480฿(电影票) |
| Promotion Discount | 营销活动折扣 | 百分比 / 固定金额 / 满减 | -50฿(新用户立减) |
| DP Fee | DP 平台手续费 | 固定 / 百分比 | +10฿ |
| Hub Fee | Hub 商户服务费 | 固定 / 百分比 / 阶梯 | +5฿ |
| Service Fee | 附加服务费 | 固定 | +20฿(选座费) |
| Tax | 税费 | 百分比 | +7%(VAT) |
| Voucher Discount | 优惠券抵扣 | 固定 / 百分比 / 封顶 | -30฿ |
| Final Price | 最终支付价格 | Base - Promo + Fee - Voucher | 435฿ |
三、数据模型
3.1 基础价格表(继承商品模型)
sku_tab(SKU 基础价格,已在商品模型中定义):
1 | -- 核心价格字段: |
dynamic_pricing_rule_tab(动态定价规则):
1 | CREATE TABLE `dynamic_pricing_rule_tab` ( |
3.2 营销活动表
promotion_activity_tab(营销活动主表):
1 | CREATE TABLE `promotion_activity_tab` ( |
discount_value JSON 配置说明:
| 折扣类型 | JSON 配置示例 | 说明 |
|---|---|---|
| percentage | {"percentage": 20} |
打8折(减20%) |
| fixed_amount | {"amount": 50} |
立减50฿ |
| full_reduction | {"threshold": 3000, "discount": 200} |
满3000减200 |
| buy_n_get_m | {"buy": 3, "free": 1} |
买3送1 |
| tiered_discount | {"tiers": [{"threshold": 500, "percentage": 5}, {"threshold": 200, "percentage": 3}]} |
阶梯折扣 |
promotion_usage_log_tab(活动使用记录):
1 | CREATE TABLE `promotion_usage_log_tab` ( |
3.3 费用配置表
fee_config_tab(费用配置表):
1 | CREATE TABLE `fee_config_tab` ( |
calculation_config JSON 配置说明:
| 计算方式 | JSON 配置示例 | 说明 |
|---|---|---|
| fixed | {"amount": 10} |
固定10฿ |
| percentage | {"percentage": 2.5} |
按基础价的2.5% |
| tiered | {"tiers": [{"threshold": 5000, "fee": 150}, {"threshold": 3000, "fee": 100}, {"threshold": 0, "fee": 50}]} |
金额阶梯 |
3.4 优惠券表
voucher_tab(优惠券主表):
1 | CREATE TABLE `voucher_tab` ( |
user_voucher_tab(用户优惠券表):
1 | CREATE TABLE `user_voucher_tab` ( |
3.5 价格快照表
price_snapshot_tab(价格快照表):
1 | CREATE TABLE `price_snapshot_tab` ( |
3.6 价格变更日志
price_change_log_tab:
1 | CREATE TABLE `price_change_log_tab` ( |
四、价格计算引擎
4.1 核心数据结构
1 | // PricingEngine 价格计算引擎 |
4.2 价格计算核心流程
1 | // Calculate 计算价格(核心入口) |
4.3 币种精度处理
不同东南亚国家的币种精度差异很大,这是必须处理的核心问题:
| 币种 | 代码 | 小数位 | 最小单位 | 示例 |
|---|---|---|---|---|
| 泰铢 | THB | 2 | 0.01 | 480.50฿ |
| 越南盾 | VND | 0 | 1 | 120000₫ |
| 印尼盾 | IDR | 0 | 1 | 85000Rp |
| 马来西亚林吉特 | MYR | 2 | 0.01 | RM 25.90 |
| 新加坡元 | SGD | 2 | 0.01 | S$12.50 |
| 菲律宾比索 | PHP | 2 | 0.01 | ₱350.00 |
1 | // roundByCurrency 按币种精度四舍五入 |
4.4 营销活动匹配器
1 | // PromotionMatcher 营销活动匹配器 |
4.5 费用计算器
1 | // FeeCalculator 费用计算器 |
4.6 价格公式生成
1 | // buildPriceFormula 构建人类可读的价格公式 |
五、核心流程设计
5.1 价格计算全流程
1 | 用户请求价格计算 |
5.2 价格一致性保障
问题:用户在商品列表、详情页、购物车、订单确认页看到的价格不一致。
1 | ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ |
方案:
1 | // 加入购物车 → 生成价格快照 |
5.3 营销活动优先级与互斥
规则矩阵:
| 活动 | Priority | Exclusivity | Voucher Compatible | 说明 |
|---|---|---|---|---|
| 秒杀特价 | 15 | 1(互斥) | 0(与券互斥) | 独占,与券互斥 |
| 新用户立减50฿ | 10 | 0(可叠加) | 1(可与券叠加) | 可叠加,可与券叠加 |
| 满3000减200 | 5 | 0(可叠加) | 1(可与券叠加) | 可叠加,可与券叠加 |
| 周末特惠 | 3 | 0(可叠加) | 1(可与券叠加) | 可叠加,可与券叠加 |
匹配流程:
1 | 活动列表(按 Priority DESC 排序) |
计算示例:
- 场景A:新用户 + 满减 → 叠加生效(-50 + -200 = -250)
- 场景B:秒杀 + 新用户 → 仅秒杀生效(秒杀优先级高且独占)
- 场景C:新用户 + 优惠券 → 叠加生效
- 场景D:秒杀 + 优惠券 → 仅秒杀生效(秒杀与券互斥)
5.4 Fee 可折扣性设计
问题:哪些费用可以被优惠券抵扣?
| 费用类型 | can_be_discounted | 原因 |
|---|---|---|
| DP Fee | 0(不可抵扣) | 平台收入,不参与优惠 |
| Hub Fee | 按协议配置 | 商户协议决定 |
| Service Fee(选座费) | 1(可抵扣) | 增值服务,可参与优惠 |
| Tax | 0(不可抵扣) | 税费不可被优惠 |
抵扣逻辑:
1 | // calculateDiscountableAmount 计算优惠券可抵扣金额 |
示例:
1 | 商品小计: 1000฿ |
六、配额并发安全
6.1 营销活动配额管理
秒杀/限量活动场景下,配额扣减必须保证原子性。使用 Redis Lua 脚本实现:
1 | -- promotion_quota_consume.lua |
6.2 优惠券核销并发安全
1 | // 优惠券核销:Redis + MySQL 双写 |
6.3 退款时优惠券/配额回退
1 | // 订单取消/退款 → 回退优惠券和配额 |
七、样例数据与计算场景
7.1 场景一:电影票购买(促销 + Fee + Voucher)
基础数据:
1 | -- SKU: 阿凡达3 IMAX 成人票 |
计算过程:
1 | 请求: user_id=100001, sku_id=2000001, quantity=2, voucher=VOUCHER_MOVIE_30 |
7.2 场景二:酒店预订(动态定价 + 满减 + 阶梯 Fee)
基础数据:
1 | -- 动态定价: 库存紧张加价15% |
计算过程:
1 | 请求: user_id=100002, sku_id=1000002(豪华房), quantity=1, context.nights=2, context.available_rooms=3 |
7.3 场景三:TopUp 充值(阶梯优惠 + 平台补贴)
1 | 请求: user_id=100003, item=AIS 500฿充值, sku_id=3000001, quantity=1 |
八、降级策略
8.1 多级降级方案
价格服务是核心链路,任何组件故障不能导致整个计算失败。
1 | ┌─────────────────────────────────────────────────────────────┐ |
8.2 降级实现
1 | // DegradeConfig 降级配置 |
8.3 降级开关配置
通过配置中心(Apollo / Nacos)动态控制降级开关,无需重启服务:
1 | { |
九、缓存策略
9.1 多级缓存架构
1 | ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ |
9.2 缓存 Key 设计
| 数据类型 | Redis Key | TTL | 说明 |
|---|---|---|---|
| SKU 基础价格 | price:base:{sku_id} |
5min | 基础价格变化不频繁 |
| 品类活动列表 | promo:active:cat:{category_id} |
5min | 缓存生效活动 |
| 费用配置 | fee:config:cat:{category_id} |
10min | 费用配置变化少 |
| 优惠券信息 | voucher:info:{voucher_code} |
5min | 券信息 |
| 活动配额 | promo:quota:{activity_id} |
无过期 | 配额计数器 |
| 价格计算结果 | price:calc:{sku_id}:{user_hash} |
60s | 短缓存,防穿透 |
9.3 缓存更新策略
1 | // 价格变更时主动失效缓存(通过 Kafka 消息驱动) |
十、Kafka 事件设计
10.1 事件类型
| 事件 | Topic | 生产者 | 消费者 | 说明 |
|---|---|---|---|---|
| 价格变更 | dp.pricing.price_changed |
价格管理后台 | Pricing Engine、搜索服务 | SKU 基础价格变更 |
| 活动创建/更新 | dp.pricing.promotion_changed |
营销管理后台 | Pricing Engine | 营销活动变更 |
| 费用配置变更 | dp.pricing.fee_changed |
费用管理后台 | Pricing Engine | 费用配置变更 |
| 价格快照生成 | dp.pricing.snapshot_created |
Pricing Engine | 数据仓库 | 快照异步落库 |
| 优惠券核销 | dp.pricing.voucher_consumed |
Pricing Engine | 优惠券服务 | 优惠券使用 |
| 退款回退 | dp.pricing.refund_rollback |
订单服务 | Pricing Engine | 退款时回退配额/券 |
10.2 事件 Schema
1 | // PriceChangeEvent 价格变更事件 |
10.3 幂等消费
1 | // 幂等处理:避免重复消费导致配额多次扣减 |
十一、性能优化
11.1 并行计算
基础价格、促销匹配、费用计算三者互相独立,可并行执行:
1 | func (e *PricingEngine) parallelCalculate(ctx context.Context, req *PriceRequest) ( |
11.2 批量价格计算
列表页需要同时计算多个商品的价格,使用批量接口减少 RPC 和 DB 调用:
1 | // BatchCalculate 批量价格计算(列表页场景) |
11.3 性能指标
| 指标 | 目标值 | 监控方式 |
|---|---|---|
| 单价计算 P50 | < 20ms | Prometheus |
| 单价计算 P99 | < 100ms | Prometheus |
| 批量计算 P99(20个) | < 200ms | Prometheus |
| 缓存命中率 | > 85% | Redis Monitor |
| QPS | > 10,000 | Load Test |
| CPU 使用率 | < 60% | Grafana |
十二、监控与告警
12.1 核心监控指标
1 | # 价格计算 QPS 和延迟 |
12.2 告警规则
| 告警名称 | 条件 | 级别 | 处理 |
|---|---|---|---|
| 价格计算超时 | P99 > 200ms 持续5分钟 | P1 | 检查缓存、DB、下游服务 |
| 降级率过高 | 降级率 > 5% 持续3分钟 | P1 | 检查促销/优惠券服务可用性 |
| 价格计算失败率 | 失败率 > 1% 持续3分钟 | P0 | 紧急排查,可能影响下单 |
| 缓存命中率下降 | 命中率 < 70% 持续5分钟 | P2 | 检查 Redis 集群状态 |
| 配额即将耗尽 | 剩余配额 < 10% | P3 | 通知运营补充配额 |
| 价格异常波动 | 同 SKU 价格波动 > 30% | P2 | 检查动态定价规则 |
12.3 价格审计
1 | // ReconstructPriceCalculation 根据订单还原价格计算(客服工具) |
十三、新品类接入指南
四步接入:
- 配置基础价格策略:确定价格来源(SKU 固定价 / 日历价 / 动态定价规则)。
- 配置费用规则:确定该品类涉及哪些费用类型,INSERT
fee_config_tab。 - 关联营销活动:在
promotion_activity_tab中category_ids加入新品类 ID。 - 注册品类策略(可选):如有特殊计价逻辑,实现
BasePriceCalculator接口。
1 | // 示例:接入新品类 "演唱会门票" |
品类接入检查清单:
| 检查项 | 说明 | 必须 |
|---|---|---|
| 基础价格来源 | SKU 固定价 / 日历价 / 动态定价 | ✅ |
| 费用配置 | 确定涉及哪些费用类型 | ✅ |
| 币种精度 | 确认该品类对应的币种和精度 | ✅ |
| 营销活动兼容 | 验证现有活动对新品类是否生效 | ✅ |
| 价格快照字段 | 确认 context 中是否需要额外字段 | ⬜ |
| 自定义计算器 | 是否需要特殊基础价格计算逻辑 | ⬜ |
十四、业界价格模型演进与对比
14.1 价格模型演进史
1 | ┌─────────────────────────────────────────────────────────────────┐ |
14.2 各阶段对比
| 维度 | Phase 1 | Phase 2 | Phase 3 | Phase 4 | Phase 5 |
|---|---|---|---|---|---|
| 计算方式 | 硬编码 | 配置化 | 规则引擎 | ML 模型 | 在线学习 |
| 响应时间 | <10ms | <50ms | <100ms | <200ms | <100ms |
| 扩展性 | 差 | 中 | 好 | 好 | 优秀 |
| 维护成本 | 高 | 中 | 中 | 中 | 低 |
| 智能程度 | 无 | 低 | 中 | 高 | 极高 |
| 代表企业 | 早期电商 | 淘宝/京东 | 天猫/Amazon | Uber/Airbnb | Amazon/阿里 |
14.3 主流电商平台对比
淘宝/天猫
1 | 价格计算链路: 商品价格 → 营销活动 → 优惠券 → 积分 → 红包 |
京东
1 | 价格计算链路: 基础价 → 会员价(Plus) → 活动 → 优惠券 → 京豆 → 运费 |
Amazon
1 | 价格计算链路: 基础价 → ML 动态定价 → Prime 折扣 → Lightning Deal → Subscribe & Save |
Uber (动态定价)
1 | 定价逻辑: base_price = distance × rate + duration × rate → surge_multiplier |
14.4 我们的定位与对比
| 特性 | 我们的设计 | 淘宝天猫 | 京东 | Amazon |
|---|---|---|---|---|
| 分层架构 | 4层(Base/Promo/Fee/Voucher) | 5层(含积分/红包) | 5层(含京豆) | 3层(简化) |
| 规则引擎 | DB 配置 + JSON | Drools + 自研 | 自研 | 自研 |
| 动态定价 | 规则驱动 | ML 驱动 | 规则驱动 | ML 驱动 |
| 价格快照 | ✅ 完整支持 | ✅ 支持 | ✅ 支持 | ✅ 支持 |
| 费用拆分 | ✅ 详细(DP/Hub/Service/Tax) | ✅ 详细 | ✅ 详细 | ✅ 详细 |
| 多币种 | ✅ 6种东南亚货币 | 单一(CNY) | 单一(CNY) | 全球多币种 |
| 降级策略 | ✅ 5级降级 | ✅ 完善 | ✅ 完善 | ✅ 完善 |
| ML 定价 | ❌ 待规划 | ✅ 深度应用 | ⚠️ 部分 | ✅ 核心能力 |
我们的差异化优势:
- 专注虚拟商品:无物流成本,关注时间维度定价(酒店日历、电影场次)。
- 费用透明化:DP Fee、Hub Fee 独立管理,可配置是否可被优惠券抵扣。
- 多币种原生支持:东南亚6国币种精度处理内置。
- 审计合规:完整价格快照 + 人类可读公式,满足监管要求。
十五、设计总结
15.1 核心设计决策
| 决策 | 选择 | 原因 |
|---|---|---|
| 统一 vs 独立 | 统一 Pricing Engine + 策略模式 | 复用计算逻辑,新品类零代码接入 |
| 同步 vs 异步 | 价格计算同步,快照异步写入 | 热路径极速,冷路径可靠 |
| 缓存策略 | L1 本地 + L2 Redis + L3 MySQL | 多级缓存,高性能 + 可靠 |
| 精度处理 | decimal.Decimal + 币种精度表 | 避免浮点误差 |
| 降级策略 | 5级降级,促销/券可降级,基础价不可降级 | 保证核心链路可用 |
| 互斥规则 | Priority + Exclusivity 字段 | 灵活配置,无需改代码 |
| 配额管理 | Redis Lua 原子操作 | 高并发场景不超卖 |
| 审计追溯 | 价格快照 + 变更日志 | 完整记录,客诉可还原 |
15.2 关键技术栈
| 组件 | 技术选型 | 说明 |
|---|---|---|
| Pricing Engine | Go 微服务 | 价格计算核心引擎 |
| 缓存层 | Redis Cluster + sync.Map | 多级缓存 |
| 规则引擎 | MySQL + JSON 配置 | 灵活配置营销规则 |
| 价格快照 | MySQL | 持久化价格明细 |
| 消息队列 | Kafka | 价格变动事件、快照异步写入 |
| 配额管理 | Redis Lua | 原子扣减 |
| 监控 | Prometheus + Grafana | 性能监控与告警 |
| 配置中心 | Apollo / Nacos | 降级开关、超时配置 |
15.3 实施路线
| 阶段 | 时间 | 内容 | 交付物 |
|---|---|---|---|
| P1: 基础架构 | 2周 | 数据库表、Pricing Engine 框架、基础价格层 | 可运行的计算引擎 |
| P2: 营销活动 | 3周 | 促销规则引擎、匹配器、配额管理、管理后台 | 支持折扣/满减/秒杀 |
| P3: 费用与优惠券 | 2周 | Fee 计算器、Voucher 系统、叠加规则 | 完整4层计算 |
| P4: 性能与审计 | 2周 | 多级缓存、并行计算、价格快照、审计工具 | P99 < 100ms |
| P5: 全量上线 | 1周 | 全品类覆盖、监控告警、文档培训 | 生产环境稳定运行 |
15.4 改进路线图
1 | ┌─────────────────────────────────────────────────────────────────┐ |
15.5 风险与缓解
| 风险 | 影响 | 缓解措施 |
|---|---|---|
| 规则配置错误 | 价格异常 | 配置审批流程 + 灰度发布 + 回滚机制 |
| 性能瓶颈 | 响应超时 | 缓存预热 + 限流降级 + 水平扩展 |
| 价格不一致 | 用户投诉 | 统一 API + 快照机制 + 实时校验 |
| 促销超卖 | 成本损失 | Redis Lua 原子扣减 + 异步对账 |
| 多币种精度 | 金额误差 | decimal.Decimal + 币种精度表 + 分摊尾差处理 |
| 缓存穿透 | DB 压力 | 布隆过滤器 + 空值缓存 + 限流 |