如何设计优惠券使用的实时规则引擎?
解读
面试官问“实时规则引擎”,不是让你写代码,而是考察你能否把业务目标、用户分层、风控、财务合规、技术落地五件事一次讲清。国内电商大促节奏快、羊毛党多,规则引擎必须在毫秒级判断用户是否可用券,同时支持运营随时改规则。因此,答案要体现“可配置、可灰度、可回滚、可监控”四大能力,并给出中国场景下的合规细节(如反垄断、价格法、个税代扣)。
知识点
- 实时决策链路:埋点→规则引擎→风控→账务→发券/扣减。
- 规则类型:准入规则(人群、渠道、城市、会员等级)、叠加规则(是否可与其他优惠同用)、预算规则(单券上限、单用户上限、总预算)、风控规则(设备、账号、行为异常)。
- 规则引擎选型:轻量级用Aviator、QLExpress;高并发用Drools+Redis缓存预计算;阿里系可用QLExpress+Blink实时流。
- 灰度与回滚:基于用户ID尾号或城市编码做白名单灰度,规则变更走配置中心(如Nacos、Apollo),版本快照+秒级回滚。
- 财务合规:优惠券在中国会计准则下属于可变对价,需按实际抵扣金额减收入,满减券要分摊到每个商品SKU;发票金额按用户实付开具,券部分不开票。
- 数据指标:券核销率、作弊率、ROI、拉新成本、复购率、客单价提升值,需实时看板,异常阈值自动告警。
答案
我给面试官一个“5层漏斗+3张表+1个热补丁方案”:
- 业务层:先确认北极星指标——本次券是拉新还是提客单。拉新就放宽门槛、提客单就设置满减梯度(如满300减30、满600减80)。
- 规则层:把规则拆成原子条件,用JSON DSL描述,例如:
{"ruleId":"123","conditions":[{"type":"userTag","op":"in","value":["new"]},{"type":"city","op":"not in","value":["港澳台"]},{"type":"amount","op":">=","value":300}],"result":{"discount":30,"maxUse":1}}
配置中心1分钟生效,运营无需发版。 - 实时层:用户下单时,先走本地缓存(Redis Hash存“用户+券”维度预计算结果),99%请求<5ms返回;缓存未命中再走Drools规则引擎,并异步写风控日志(设备指纹、IP、历史订单)。
- 预算层:用Redis Lua脚本做原子扣减,key=“券ID+日期”,value=剩余预算;扣减失败直接降级到“券已抢光”文案,避免超发。
- 灰度层:新规则先放10%用户ID尾号=3的桶,**核心指标(核销率、作弊率)与对照桶差异<2%**才全量。
- 三张核心表:
- 规则表(rule_config):存DSL、状态、版本号;
- 用户券实例表(user_coupon):存用户领到的券及使用状态,加唯一索引防重复领;
- 预算流水表(budget_log):每条预算扣减写一条日志,用于财务对账与反作弊溯源。
- 热补丁:如果线上出现**“薅羊毛”漏洞**,30秒内通过配置中心把规则DSL里的条件值改掉,并推送Kafka消息让各应用节点刷新本地缓存,无需重启。
最后用实时看板监控:券核销率低于15%或作弊率高于5%立即自动熔断,短信+飞书群通知运营负责人。
拓展思考
- 如果抖音直播间发券,瞬时QPS是日常100倍,可把规则引擎前置到CDN边缘节点,只保留人群标签缓存,预算扣减异步消息队列(RocketMQ)削峰,最终一致性。
- 面对政府消费券,需对接银联/微信/支付宝的券平台接口,规则引擎要输出标准JSF/HTTPS协议,并加密签名防篡改,预算由财政局实时拨付,超预算需秒级停发。
- 未来想做个性化券面额,可引入实时模型分:把用户LTV预测分、价格敏感度分作为规则变量,模型分每15分钟更新一次,规则引擎里直接引用,实现千人千券,预估ROI提升8%以上。