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

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

本文将分享其技术架构。

一、优惠券的数据模型

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 限流,在高并发场景下稳定运行。这套设计可以复用到大多数电商平台的营销系统中。

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

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

相关推荐
慧都小妮子2 小时前
不想频繁改 PLC?用 DeviceXPlorer Lua 脚本把产线业务逻辑放到 OPC Server 层
java·junit·lua·takebishi·dxpserver·设备数据采集软件·opc server
闪电悠米2 天前
黑马点评-Redis 消息队列-03_stream_consumer_group
开发语言·数据库·redis·分布式·缓存·junit·lua
闪电悠米2 天前
黑马点评-Redis 消息队列-04_stream_seckill_order
数据库·redis·分布式·缓存·oracle·junit·lua
摇滚侠2 天前
Spring 零基础入门到进阶 单元测试 JUnit 52-60
spring·junit·单元测试
呦呦鹿鸣Rzh2 天前
Redis Lua 脚本:从入门到避坑指南
redis·junit·lua
闪电悠米3 天前
黑马点评-Redis 消息队列-01_why_redis_mq
java·数据库·spring boot·redis·缓存·junit·消息队列
ourenjiang4 天前
【测试框架Junit】强制终止JVM进程
jvm·junit
闪电悠米6 天前
黑马点评-秒杀优化-04_lua_and_db_fallback
服务器·开发语言·网络·数据库·缓存·junit·lua
闪电悠米6 天前
黑马点评-秒杀优化-03_blocking_queue_async_order
数据库·分布式·oracle·junit·wpf·lua