日淘平台优惠券系统的设计:从规则引擎到防超领

日淘平台为了吸引用户,通常会提供多种优惠券功能 :新人券、运费券、满减券、节日券等。北极星日淘 的优惠券系统每天处理数万次领券和核销请求,必须保证高并发下的准确性和一致性。

本文将分享其技术架构。

一、优惠券的数据模型

CREATE TABLE `coupon` ( `id` bigint PRIMARY KEY AUTO_INCREMENT, `name` varchar(100) NOT NULL, `type` tinyint COMMENT '1:满减 2:折扣 3:运费减免', `threshold` int COMMENT '使用门槛(分)', `reduce_amount` int COMMENT '减免金额(分)', `total_quantity` int COMMENT '总发行量', `remain_quantity` int COMMENT '剩余数量', `per_user_limit` int DEFAULT 1 COMMENT '每人限领', `start_time` datetime, `end_time` datetime);

二、高并发领券:Redis 预扣库存

直接操作 MySQL 会导致行锁竞争。北极星日淘 使用 Redis + Lua 脚本实现原子性扣减。

-- 领券 Lua 脚本 local key = KEYS1 -- 优惠券库存 key local user_key = KEYS2 -- 用户已领 key local user_id = ARGV1local limit = tonumber(ARGV2)local user_count = redis.call('scard', user_key)if user_count >= limit then return -1 -- 超过限领数量 endlocal remain = redis.call('get', key)if not remain or tonumber(remain) <= 0 then return -2 -- 库存不足 endredis.call('decr', key)redis.call('sadd', user_key, user_id)return 1

三、规则引擎:动态匹配最优券

用户下单时,系统需要从多张可用券中自动选择最优惠的一张。北极星日淘 引入了 Drools 规则引擎。

rule "Auto choose best coupon" when order: Order(totalAmount \> 0) couponList: ArrayList(size > 0) from couponService.getAvailableCoupons(order) then Coupon best = null; for (Coupon c : couponList) { if (best == null || c.calcDiscount(order) \> best.calcDiscount(order)) { best = c; } } $order.setSelectedCoupon(best);end

四、防超领和作弊

为了防止用户恶意刷券,系统还做了以下限制:

同一用户 ID、同一设备指纹、同一 IP 在短时间内多次领券会被限流。使用 Sentinel 熔断降级,当领券 QPS 超过阈值时,自动返回兜底逻辑。

spring: cloud: sentinel: flow: - resource: "receiveCoupon" count: 100 grade: 1 # QPS 限流

五、总结

北极星日淘 的优惠券系统采用 Redis 预扣库存 + Lua 原子操作 + Drools 规则引擎 + Sentinel 限流,在高并发场景下稳定运行。这套设计可以复用到大多数电商平台的营销系统中。

对于后端开发者,尤其是电商系统开发者,这是一个非常经典的设计案例。

#优惠券功能 #规则引擎 #高并发 #北极星日淘

相关推荐
努力努力再努力wz2 天前
【Lua 进阶系列】从 C++ 对象到 Lua 变量:一文理解 userdata、Lua 栈与元表绑定机制
c++·junit·lua
努力努力再努力wz6 天前
【Lua进阶系列】Lua 调试机制详解:从虚拟机调用栈、错误传播到 debug 库
junit·单元测试·lua
BuHuaX10 天前
Lua 与 ToLua:运行机制及热更新原理
开发语言·unity·junit·c#·lua
海棠Flower未眠10 天前
下单请求处理流程:商品维度分布式锁与 Redis 预扣库存
redis·分布式·junit
努力努力再努力wz11 天前
【Lua 入门系列】模块与包(一):从多文件组织到require 运行时加载机制、模块缓存、预加载搜索与 Lua 文件搜索机制
开发语言·junit·lua
CarIise12 天前
Spring 框架:多配置文件、开发方式与 IOC 注解
junit·maven·jar
努力努力再努力wz12 天前
【Lua入门系列】从 Table 到元表与元方法:一文理解 Lua 的行为扩展机制
开发语言·junit·lua
麻瓜code13 天前
秒杀优化三连:Lua + 阻塞队列 + Redis Stream,响应从 3.4 秒到毫秒级
redis·junit·lua
努力努力再努力wz15 天前
【Lua 入门系列】从顺序执行到分支与循环:一文理解 Lua 控制结构、作用域与跳转规则
junit·单元测试·lua
努力努力再努力wz16 天前
【Lua入门系列】从动态类型到变量作用域:彻底理解 local、全局变量与跨文件访问
开发语言·junit·lua