要求说明
在开发优惠券系统或票务系统时,往往需要生成纯数字代码,优惠券代码要求:12位纯数字,不规则,不重复。
下面我提供一个想法,使用 Redis 的列表数据类型,lpop+rpush 来维护 10,000 个代码的队列。
队列数据结构
保持10,000个优惠券代码的数量,可根据项目实际情况进行调整。
array
客户
Redis 的 LPOP 方法取出指定数量的优惠券代码。
如果队列中的优惠券代码数量不足,则有回退计划,不足的部分用随机数填充。
知识点:LPOP是原子性的,在高并发场景下,即使多个用户同时拿到优惠券码,也会按照优先级顺序一一执行,这样保证每个用户拿出的优惠券码不会重复。
@从队列中取出指定数量的券码。维护队列优惠券代码的数量有一个脚本会定期检查队列并找出消耗了多少优惠券代码,因此它会将多个优惠券代码推送到其中。参数$num优惠券代码的数量。
返回数组 返回一个优惠券代码数组。
function getcode($num)
如果队列中没有足够的优惠券代码,则将随机生成不足的部分。
if(count($codearr)
return $codearr;
新生成的随机数优惠券代码应与数据库进行比对,如果优惠券代码已经存在,则应将其丢弃并重新生成。
知识点:rpush 也是原子的,当 rpush 数据时,尽量一次插入多个优惠券码,以减少用户的排队时间。
*例。
codedata=$redis->lrange($key,0,-1);取出优惠券代码队列中的所有数据。codedata=!is_array($codedata)?[codedata;
len=count($codedata);
diff=10000-$len;失踪了多少。
validarr=;有效的验证码。
if($diff>0)
filterarr="'".$code."'";
validarr=$code;
if(count($filterarr)==0)
了解优惠券代码是否已被使用。
usedarr=;
filter_str=implode(",",$filterarr);
sql="select distinct `code` from `user_code` where `code` in ()";
tmpdata=db::query($sql);
foreach($tmpdata as $k=>$v)
unset($tmpdata);
validarr=array_diff($validarr,$usedarr);减去数据库中已使用的内容。
if(count($validarr)
项目清单
笔者所在公司的票务系统,使用这个优惠券代码方案,已经稳定运行多年,年数据上千万。