电商限购怎么做?聊聊我踩过的坑和一套落地配置思路
电商限购怎么做?聊聊我踩过的坑和一套落地配置思路-佛山z35资讯网
前年我给一个做母婴用品的客户改商城,活动上线第二天就出事了:一款9块9的纸尿裤被同一个手机号下了87单,仓库打包到凌晨。老板在群里问“限购不是做了吗”,我打开后台一看,规则确实配了,配的是“每单限购2件”。说白了,人家一次下一单,下87次,规则一点没拦住。
这件事之后我把限购这块重新理了一遍。限购这功能听着简单,真做起来细节特别多,坑都在边界条件上。

先想清楚三个维度再动手
很多人一上手就写代码,写到一半发现需求对不上。我的习惯是先跟运营把三件事问清楚,做成一张表:

- 限谁:按用户ID、手机号、设备号、IP还是收货地址?只按用户ID最省事,但挡不住黄牛批量注册
- 限什么:限单个SKU、限整个SPU,还是限某一场活动的全部商品
- 限多久:单笔订单内限、每天限、活动期间累计限,还是账号终身限

这三组参数组合起来才是完整的规则。上面那个纸尿裤的例子,正确的配置应该是“按手机号 + 单个SKU + 活动期间累计 + 最多2件”。维度选错一个,功能等于没做。
计数时机选错,活动基本白做
第二件要定的事,是额度什么时候被占用。我见过两种做法,结果差很远。
一种是下单即占用,创建订单就给用户扣掉额度。好处是能挡住恶意刷单,坏处是用户拍下不付款,额度被占着,半小时后订单自动取消才释放。大促期间支付通道一堵,一堆用户卡在“您已超出限购数量”的提示上,投诉电话打爆。
另一种是支付成功才计数。用户体验好,但并发场景下容易穿透,两个人同时支付,额度都通过了。
我后来用的是折中方案:下单时先在Redis里原子自增占位,设置一个跟订单超时时间一致的过期时间,支付成功后把占位转成正式记录写库,订单取消或者超时就让key自然过期。这样既能挡住并发,也不会把额度锁死太久。
并发这块必须用原子操作,别用“先查询再判断再写入”那套。我第一版就是这么写的,压测时100个并发跑过去,成功扣到额度的是103次。后来改成Redis的incr,判断返回值有没有超过上限,超了就直接回滚减一。库存扣减和限购计数要放在同一个逻辑里,中间任何一步失败都得整体回滚,不然账就乱了。
后台配置和几个真实踩过的坑
后台这块我的建议是做成规则表,别把限购条件硬编码在代码里。字段大致是:活动ID、商品范围、限制维度、限制周期、限制数量、生效时间、是否包含退款订单。运营自己就能配,不用每次改规则都发版。
下面这几个坑是我和同行都遇到过的,写出来供参考:
- 退款后额度要不要恢复?我的做法是大促商品不恢复,防止有人先买后退再买,把赠品刷走;日常商品恢复,客服手动处理
- 多端不同步。小程序、App、H5各算各的,用户在三个端各买一份,等于限购乘了三倍。计数一定要落在服务端统一的地方
- 游客和登录用户的口径。未登录时按设备号限,登录后合并到用户ID,合并逻辑写不好会出现“登录后额度变多”的漏洞
- 提示文案。只写“超出限购”用户会反复试,改成“该商品活动期间每人限购2件,您已购买2件”,客服咨询量能降一半
还有一点,限购规则的判定要放在下单链路的最前面,别等库存扣完了才发现超限,回滚成本高,还容易出脏数据。
讲真,限购这东西技术难度不高,难的是把业务场景想全。上线前我通常会做一轮自测:同一账号连下三单、两个账号同IP同时下单、下单不付款等超时、付款后退款再买。这四个场景跑通了,基本就不会出大问题。规则配置之前多问运营几句“你到底想拦住谁”,比事后改代码省事得多。