Arch Day 70: 促销系统设计
Arch Day 70: 促销系统设计
日期: 2026-06-08 (Day 70) 阶段: 第三阶段 - 零售域深度 标签: #电商 #促销系统 #规则引擎 #动态定价 #AI定价
核心概念
一句话定义
促销系统是电商的"增长引擎",通过规则引擎驱动多种优惠策略(优惠券/满减/折扣/秒杀/拼团等),在正确的时间、对正确的用户、以正确的价格促成交易——但同时也是系统复杂度的"炸弹"。
为什么关注
据2025年行业数据,采用动态定价策略的零售商在前6个月内收入平均提升10%-25%(Grid Dynamics Report)。Composable Commerce架构中,Pricing & Promotions已成为独立微服务,是电商技术栈的核心能力之一(commercetools 2026)。2025年最显著的信号是"温和折扣的消亡"——传统小幅优惠已失效,消费者期待更激进、更个性化的促销体验。
误区与反模式
| 误区 | 现实 |
|---|---|
| "促销就是改价格" | 促销涉及规则定义、条件匹配、叠加计算、分摊、核销全链路 |
| "所有优惠都能叠加" | 需要严格的互斥/叠加矩阵,否则会出现"薅羊毛"漏洞 |
| "先算总价再减优惠" | 需要先确定优惠分摊到每个商品,否则退款时无法计算 |
| "促销配置后立即生效" | 大规模SKU价格变更需要预计算+缓存预热+灰度发布 |
| "规则越多越灵活" | 规则爆炸会导致冲突检测困难和计算性能下降 |
知识点详解
一、促销类型全景
1.1 基础促销类型
| 类型 | 机制 | 复杂度 | 示例 |
|---|---|---|---|
| 优惠券 | 用户主动领取/发放→核销 | 中 | 满100减20券 |
| 满减 | 购物车满足条件自动触发 | 中 | 每满300减50 |
| 折扣 | 商品级直接打折 | 低 | 8折特卖 |
| 秒杀 | 限时限量特价 | 高 | 0元秒杀 |
| 拼团 | 多人凑团享优惠 | 高 | 3人团立减50% |
| 预售 | 先付定金后付尾款 | 高 | 定金翻倍 |
| 赠品 | 满足条件赠送商品 | 中 | 买手机送耳机 |
| N件M折 | 多件购买享折扣 | 中 | 第二件半价 |
| 满赠 | 满足金额/数量送赠品 | 中 | 满500送袋子 |
| 阶梯价 | 数量越多价格越低 | 中 | 1件10元,3件8元/件 |
| 组合促销 | 指定商品搭配购买优惠 | 高 | A+B组合立减30 |
1.2 促销生命周期
创建 → 审核 → 待生效 → 生效中 → 已结束 → 已归档
│ │ │ │
│ │ 驳回 │ 提前终止 │ 效果分析
▼ ▼ ▼ ▼
草稿 已驳回 已终止 报告
二、促销叠加规则
2.1 互斥与叠加矩阵
这是促销系统最核心的设计难点之一:
│ 优惠券 │ 满减 │ 折扣 │ 秒杀 │ 拼团 │ 赠品
───────────┼────────┼───────┼───────┼───────┼───────┼──────
优惠券 │ 互斥 │ 可叠加 │ 可叠加 │ 互斥 │ 互斥 │ 可叠加
满减 │ 可叠加 │ 互斥 │ 可叠加 │ 互斥 │ 互斥 │ 可叠加
折扣 │ 可叠加 │ 可叠加 │ 互斥 │ 互斥 │ 互斥 │ 可叠加
秒杀 │ 互斥 │ 互斥 │ 互斥 │ 互斥 │ 互斥 │ 互斥
拼团 │ 互斥 │ 互斥 │ 互斥 │ 互斥 │ 互斥 │ 互斥
赠品 │ 可叠加 │ 可叠加 │ 可叠加 │ 互斥 │ 互斥 │ 可叠加
2.2 叠加计算顺序
叠加顺序直接影响最终价格,业界通常约定:
原价 → 商品级优惠(折扣/秒杀) → 订单级优惠(满减) → 跨店优惠(平台满减) → 优惠券 → 支付优惠(银行卡减免)
class PromotionCalculator:
"""促销叠加计算引擎"""
# 计算层级:从底层到顶层
CALCULATION_LAYERS = [
'ITEM_LEVEL', # 1. 商品级:折扣/秒杀/N件M折
'SHOP_LEVEL', # 2. 店铺级:店铺满减/店铺券
'PLATFORM_LEVEL', # 3. 平台级:平台满减/平台券/跨店满减
'PAYMENT_LEVEL', # 4. 支付级:银行卡优惠/支付宝红包
]
def calculate(self, cart, available_promotions):
"""
多层级叠加计算
"""
current_prices = {item.id: item.original_price for item in cart.items}
for layer in self.CALCULATION_LAYERS:
layer_promotions = [p for p in available_promotions if p.layer == layer]
# 同层互斥:选择最优
best_promotion = self.find_best_in_layer(
layer_promotions, cart, current_prices
)
if best_promotion:
current_prices = self.apply_promotion(
best_promotion, cart, current_prices
)
return current_prices
def find_best_in_layer(self, promotions, cart, current_prices):
"""同层促销互斥,选对用户最优的"""
best = None
max_discount = 0
for promo in promotions:
if promo.check_condition(cart, current_prices):
discount = promo.calculate_discount(cart, current_prices)
if discount > max_discount:
max_discount = discount
best = promo
return best
三、价格计算引擎
3.1 引擎核心流程
┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐
│ 商品原价 │───→│ 条件匹配 │───→│ 优惠计算 │───→│ 叠加判定 │───→│ 分摊输出 │
│ Original │ │ Matching │ │ Discount │ │ Stacking │ │ Spread │
└─────────┘ └──────────┘ └──────────┘ └──────────┘ └─────────┘
│ │ │
▼ ▼ ▼
条件DSL 计算公式 互斥矩阵
3.2 规则DSL设计
{
"rule_id": "PROMO_2026_618_01",
"name": "618大促满300减50",
"type": "FULL_REDUCTION",
"layer": "PLATFORM_LEVEL",
"priority": 100,
"condition": {
"operator": "AND",
"rules": [
{"field": "cart.total_amount", "op": ">=", "value": 300},
{"field": "cart.item_count", "op": ">=", "value": 1},
{"field": "user.is_new", "op": "==", "value": false},
{"field": "item.category", "op": "NOT_IN", "value": ["digital_card", "insurance"]}
]
},
"action": {
"type": "AMOUNT_OFF",
"value": 50,
"repeat": true,
"max_discount": 200
},
"exclusion": ["FLASH_SALE", "GROUP_BUY"],
"effective_period": {
"start": "2026-06-01T00:00:00",
"end": "2026-06-18T23:59:59"
},
"budget": {
"total": 10000000,
"per_user": 200,
"per_order": 200
}
}
3.3 优惠分摊算法
优惠分摊是为了退款时能精确计算每件商品应退多少钱。
def spread_discount(items, total_discount):
"""
按金额比例分摊优惠到每个商品
使用"最大余数法"避免精度丢失
"""
total_amount = sum(item.price * item.qty for item in items)
# 第一轮:按比例分摊(截断到分)
spread_result = []
allocated = Decimal('0')
for item in items:
item_amount = item.price * item.qty
ratio = item_amount / total_amount
# 截断到分(不四舍五入,避免总和超出)
item_discount = (total_discount * ratio).quantize(
Decimal('0.01'), rounding=ROUND_DOWN
)
spread_result.append({
'item_id': item.id,
'discount': item_discount,
'remainder': float(total_discount * ratio - item_discount)
})
allocated += item_discount
# 第二轮:剩余金额分配给余数最大的商品
remaining = total_discount - allocated
if remaining > 0:
# 按余数排序,将剩余的分分配下去
spread_result.sort(key=lambda x: x['remainder'], reverse=True)
i = 0
while remaining > 0:
spread_result[i]['discount'] += Decimal('0.01')
remaining -= Decimal('0.01')
i = (i + 1) % len(spread_result)
return spread_result
四、促销规则引擎架构
4.1 整体架构
┌──────────────────────────────────────────────────────────────┐
│ 促销管理后台 │
│ 规则配置 │ 活动管理 │ 预算管理 │ 效果分析 │ 冲突检测 │
└──────────────────────────┬───────────────────────────────────┘
│
┌──────────────────────────▼───────────────────────────────────┐
│ 规则引擎服务 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 规则编译器 │ │ 条件匹配器│ │ 优惠计算器│ │ 分摊计算器│ │
│ │ Compiler │ │ Matcher │ │ Calculator│ │ Spreader │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 互斥检测器│ │ 预算管控器│ │ 冲突检测器│ │
│ │ Exclusion│ │ Budget │ │ Conflict │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└──────────────────────────┬───────────────────────────────────┘
│
┌──────────────────────────▼───────────────────────────────────┐
│ 数据存储层 │
│ MySQL(规则定义) │ Redis(活动缓存/库存/预算) │ ES(规则检索) │
└──────────────────────────────────────────────────────────────┘
4.2 大促价格预计算
面对"分钟级万级SKU价格变更"的挑战,核心方案是预计算+增量更新:
T-24h: 促销规则冻结,开始预计算
│
├── 离线任务:遍历所有SKU × 所有活动规则,计算促销价
├── 结果写入: Redis Hash (sku_id → promo_price)
├── CDN预热: 商品详情页静态化
│
T-1h: 增量更新最后调整的规则
│
T-0: 大促开始
│
├── 读取路径: CDN → Redis → 计算引擎(兜底)
└── 热点SKU: 本地缓存(Caffeine) + Redis
五、优惠券系统详解
5.1 优惠券生命周期
创建批次 → 生成券码 → 投放(发放) → 领取 → 锁定(下单) → 核销(支付) → 退回(退款)
5.2 券码生成策略
| 策略 | 说明 | 场景 |
|---|---|---|
| 预生成 | 提前生成固定数量券码 | 限量发放 |
| 实时生成 | 用户领取时生成 | 无限量(有总预算) |
| 通用码 | 单一码多人使用 | 渠道推广(如"SUMMER20") |
| 唯一码 | 每张券唯一 | 防止分享滥用 |
5.3 防薅羊毛策略
class AntiAbuseEngine:
"""防薅羊毛引擎"""
def check(self, user, coupon_batch):
checks = [
self.check_frequency(user), # 领取频率限制
self.check_device_bindling(user), # 设备绑定
self.check_ip_limit(user), # IP限制
self.check_phone_bindling(user), # 手机号限制
self.check_behavior_pattern(user), # 行为模式异常检测
self.check_social_graph(user), # 社交关系图谱
]
return all(checks)
def check_behavior_pattern(self, user):
"""AI检测异常行为模式"""
features = {
'register_age_hours': user.register_age_hours,
'order_count': user.order_count,
'coupon_usage_rate': user.coupon_usage_rate,
'avg_order_interval': user.avg_order_interval,
'device_count': user.device_count,
}
risk_score = self.ml_model.predict(features)
return risk_score < 0.7 # 低于阈值才放行
对比分析
促销规则引擎技术方案对比
| 维度 | 硬编码 | Drools规则引擎 | 自研DSL引擎 | 低代码配置平台 |
|---|---|---|---|---|
| 灵活性 | 极低 | 高 | 高 | 中 |
| 性能 | 最高 | 中(Rete算法) | 高(可优化) | 中 |
| 运营自助 | 不可能 | 需要学习DRL | 可视化配置 | 最友好 |
| 开发成本 | 低(初期) | 中 | 高 | 中 |
| 维护成本 | 极高 | 中 | 中 | 低 |
| 冲突检测 | 手动 | 内置 | 需自研 | 内置 |
| 适用阶段 | 早期/MVP | 中大型 | 大型定制 | 中型标准化 |
| 典型使用 | 小型电商 | 银行/保险 | 淘宝/京东 | Shopify应用 |
主流电商促销架构对比
| 维度 | 淘宝/天猫 | 京东 | Shopify | commercetools |
|---|---|---|---|---|
| 引擎类型 | 自研UMP | 自研 | 应用生态 | API-first |
| 规则数量级 | 百万级 | 十万级 | 千级 | 万级 |
| 叠加层级 | 5层 | 4层 | 2-3层 | 可配置 |
| 大促QPS | 百万级 | 十万级 | 万级 | 万级 |
| AI定价 | 深度集成 | 深度集成 | 第三方 | 第三方 |
架构设计实操
设计目标
设计一个促销规则引擎,支持:
- 万级SKU分钟级价格变更
- 10+促销类型,可扩展
- 多层叠加计算,同层互斥
- 运营自助配置(低代码)
- 大促峰值10万QPS
方案架构
┌──────────────────────────────────────────────────────────────┐
│ 运营管理台(低代码) │
│ 可视化规则编辑 │ 活动日历 │ 预算看板 │ 效果分析 │ 冲突检测 │
└──────────────────────────┬───────────────────────────────────┘
│ 规则发布(版本化)
┌──────────────────────────▼───────────────────────────────────┐
│ 规则分发服务 │
│ 规则编译 → 规则版本管理 → 推送到各节点本地缓存 │
└──────────────────────────┬───────────────────────────────────┘
│
┌──────────────────────────▼───────────────────────────────────┐
│ 计算引擎集群 │
│ ┌─────────┐ ┌─────────────────────────────────────┐ │
│ │本地规则 │ │ 计算流水线 │ │
│ │缓存 │──→│ 条件匹配→互斥判定→优惠计算→叠加→分摊 │ │
│ │(Caffeine)│ └─────────────────────────────────────┘ │
│ └─────────┘ │
└──────────────────────────────────────────────────────────────┘
ADR: 促销规则存储与分发
背景: 促销规则频繁变更,但计算时对性能要求极高
决策: 规则定义存MySQL → 编译为可执行对象 → 推送到计算节点本地缓存
理由:
- 规则变更频率低(分钟级),但计算频率极高(每次加购/结算都要算)
- 本地缓存避免网络IO,计算延迟<10ms
- 规则版本化 + 灰度发布确保安全
权衡:
- 优势:计算性能极高、规则可热更新
- 劣势:本地缓存一致性有短暂延迟(秒级)、内存占用
- 替代方案:每次从Redis读规则(网络IO,延迟较高)
AI增强实践
1. AI动态定价引擎
class AIDynamicPricingEngine:
"""
AI驱动的动态定价引擎
据行业数据,动态定价可提升10-25%收入(Grid Dynamics 2025)
"""
def calculate_optimal_price(self, sku, context):
"""
基于多维度信号计算最优价格
"""
features = {
# 市场信号
'competitor_price': self.get_competitor_price(sku),
'market_demand_index': self.get_demand_index(sku),
# 库存信号
'inventory_level': sku.stock,
'days_since_arrival': sku.days_in_warehouse,
'sell_through_rate': sku.sell_through_rate,
# 用户信号
'user_price_sensitivity': context.user.price_sensitivity,
'user_ltv': context.user.lifetime_value,
'user_segment': context.user.segment,
# 时间信号
'day_of_week': context.day_of_week,
'hour_of_day': context.hour,
'is_holiday': context.is_holiday,
'days_to_next_promo': context.days_to_next_promo,
# 外部信号
'weather': context.weather,
'economic_indicator': context.cpi_index,
}
# 模型预测最优价格
optimal_price = self.pricing_model.predict(features)
# 护栏:确保在合理范围内
floor_price = sku.cost * 1.1 # 不低于成本+10%
ceiling_price = sku.original_price * 1.2 # 不高于原价120%
optimal_price = max(floor_price, min(optimal_price, ceiling_price))
return optimal_price
def ab_test_pricing(self, sku, variants):
"""A/B测试不同定价策略"""
# 多臂老虎机算法(Thompson Sampling)选择最优变体
selected = self.thompson_sampling.select(variants)
return selected.price
2. AI促销效果预测
| AI能力 | 应用 | 输入 | 输出 |
|---|---|---|---|
| 促销效果预测 | 活动上线前预估ROI | 历史数据+规则参数 | 预计GMV/订单量/成本 |
| 智能推荐优惠 | 个性化优惠推荐 | 用户画像+浏览行为 | 最优优惠组合 |
| 预算优化 | 在预算内最大化GMV | 总预算+多活动候选 | 各活动最优预算分配 |
| 价格弹性分析 | 评估降价敏感度 | 历史价格变动+销量 | 需求曲线/弹性系数 |
| 竞价监控 | 实时跟踪竞品价格 | 爬虫数据+API | 价格异动告警+建议 |
3. LLM辅助促销文案生成
def generate_promotion_copy(promotion):
"""LLM生成促销文案"""
prompt = f"""
你是一个电商促销文案专家。请为以下促销活动生成3个版本的文案:
- 活动类型: {promotion.type}
- 优惠力度: {promotion.discount_description}
- 目标用户: {promotion.target_segment}
- 商品品类: {promotion.category}
- 活动时间: {promotion.period}
要求:
1. 版本A: 紧迫感导向(限时/限量)
2. 版本B: 价值感导向(省钱/划算)
3. 版本C: 社交导向(分享/拼团)
每个版本包含:标题(15字内) + 副标题(25字内) + CTA按钮文案(6字内)
"""
return llm.generate(prompt)
与Web3/DeFi的关联
促销系统 × Web3
| Web2促销痛点 | Web3解决方案 | 实现方式 |
|---|---|---|
| 优惠券造假 | NFT化优惠券 | ERC-721优惠券,链上验证真伪 |
| 黄牛囤券转卖 | 灵魂绑定(SBT) | SBT优惠券不可转让 |
| 跨平台无法使用 | 链上通用券 | 去中心化优惠协议 |
| 活动规则不透明 | 链上规则公开 | 智能合约定义促销规则 |
| 数据孤岛 | DID+链上消费记录 | 统一的用户促销历史 |
Token激励 vs 传统促销
传统促销: 平台发券 → 用户使用 → 平台承担成本 → 用完即止
Token激励: 协议发Token → 用户赚取 → 可交易/质押 → 持续参与
DeFi的"流动性挖矿"本质就是一种促销:
- "优惠券" = Token奖励
- "满减" = TVL达标奖励
- "秒杀" = 限时高APY
- "拼团" = 社区Pool
今日思考
1. 促销规则冲突如何自动检测?
当运营同时配置上百条促销规则时,如何自动发现冲突?核心思路是建立"规则影响域"模型——每条规则影响的SKU集合和时间区间。两条规则的影响域交集非空且类型互斥时,即为冲突。可以用时空索引(R-Tree)加速检测。更进阶的方案是引入AI预测——在规则保存前模拟计算样本订单,检查是否出现"0元购"或"优惠超原价"等异常。
2. 如何防止大促期间的"价格计算风暴"?
618/双11瞬间流量可达平时100倍。应对策略:(1) 预计算:T-24h将促销价写入缓存;(2) 本地缓存:Caffeine缓存热门SKU的计算结果;(3) 降级:极端情况下跳过复杂叠加计算,使用预计算价格兜底;(4) 异步化:非关键路径(如积分、赠品)异步处理。
3. 个性化定价(Price Discrimination)的伦理边界在哪?
AI动态定价可以对不同用户显示不同价格。技术上可行,但法律和伦理边界模糊。中国《价格法》要求"明码标价",欧盟GDPR对自动化决策有知情权要求。建议做法:(1) 个性化的是"优惠力度"而非"标价";(2) 基于行为而非人群画像定价;(3) 提供价格解释功能。
面试题准备
题目:如何设计支持"分钟级万级SKU价格变更"的促销系统?
30秒回答: 采用"规则预编译+多级缓存+异步预计算"架构。规则变更后编译为可执行对象推送到计算节点本地缓存,热门SKU的价格提前计算写入Redis,实时计算作为兜底。通过版本化 + 灰度发布保证变更安全。
2分钟回答:
问题拆解:万级SKU × 分钟级变更 = 每分钟可能触发百万次价格重算
方案设计(四层架构):
- 规则层:促销规则存MySQL,变更后编译为可执行规则对象(类似正则预编译),通过消息推送到各计算节点
- 预计算层:后台任务监听规则变更事件,增量计算受影响SKU的新价格,结果写入Redis
- 缓存层:三级缓存——本地Caffeine(热SKU, <1ms) → Redis(全量, <5ms) → 实时计算(兜底, <50ms)
- 降级层:极端情况(缓存全部失效),使用上一版本的缓存价格 + 异步刷新
性能优化关键点:
- 增量计算:只重算受影响的SKU(通过规则-SKU映射表确定影响范围)
- 批量处理:Redis Pipeline批量写入
- 分片并行:按SKU分片,多台机器并行计算
- 预热:大促前全量预计算 + CDN静态化
安全保障:
- 规则版本化:每次变更生成新版本号
- 灰度发布:先小流量验证,再全量生效
- 价格护栏:自动检测异常价格(<成本价或>原价200%)
追问准备:
- Q: 缓存和DB不一致怎么办?→ 最终一致性 + 定时对账 + 价格校验(下单时二次验算)
- Q: 热点SKU(全网同一个爆款)怎么扛?→ 本地缓存+JVM级计算,避免Redis热点
- Q: 退款时价格变了怎么办?→ 订单快照记录下单时刻的价格和促销详情
学习资源
- Spree 5 Advanced Promotions Engine
- How to Replatform a Pricing Engine - Grid Dynamics
- Commerce Capabilities 101: Pricing & Promotions - commercetools
- Dynamic Pricing Algorithms in 2026 - AIMultiple
- Real-time Pricing Engines for Ecommerce - Studio Ubique
- The Pricing Engine - Talon.One
明日预告
Day 71: 购物车与结算链路 —— 购物车看似简单,实际暗藏复杂度(游客车合并、价格一致性、高并发下单)。我们将深入结算页的全链路设计,分析库存预扣→订单创建→支付确认的完整流程,以及高并发场景下的性能优化方案。