袋鼠玩趣城小程序优惠券重复领取问题分析与PHP后端解决方案

在我的袋鼠玩趣城小程序项目里,当用户进行领取优惠券的操作时,出现了数据重复记录的情况。这意味着原本每人只能领取一张的操作,却有个别用户领到了 2 张或者 3 张。

袋鼠玩趣城小程序优惠券重复领取问题分析与PHP后端解决方案

分析了原因,在网络状态不好时,用户多次点击了领取按钮,从而导致了类似高并发的场景。

解决办法:

从前端进行解决,这种方法能够缓解一部分问题,不过我个人认为无法彻底杜绝。

小程序的前端加上 防抖操作或者做节流操作

2:从后端解决,(php 后端)

方法又有三种

a: 使用php的文件锁

//这里为高并发的情况加上文件销
使用“w+”模式打开名为“./lock.mytxt”的文件,并将其句柄赋值给变量$handle。
如果使用 flock 函数以独占锁(LOCK_EX)的方式锁定了 $handle ,那么就会执行后续的操作。如果没有成功锁定 $handle ,则不会执行后续操作。
$free_ticket_model 获取免费门票,传入参数 $id、$store_id 和当前用户的用户 ID $this->userInfo["uid"],最终结果赋值给 $result
            flock($handle, LOCK_UN);
            fclose($handle);
            if ($result["error"] == 0) {
使用 JsonService 成功返回 "ok"。
            } else {
使用 JsonService 的 fail 方法,并传入 result 中的 "msg" 作为参数。
            }
        }

要记录完成操作后,解锁,并且释放资源

使用 mysql 数据库时可使用类似 select * from table for update 的锁操作。

通过"order_id"来查找与指定"order_id"匹配的 StoreOrderShare 记录,在查找过程中进行锁定,最终找到的记录赋值给$store_order_share 。

这是一个tp5中的加锁的方式

注意,只有和 mysql 的事务一起使用时这个写法才有效。也就是说,上面的这句话必须是在执行 Db::startTrans(); 之后。

说到数据库时,存在一个能解决重复写入问题的方法,即使用数据库的索引,特别是唯一索引。倘若有重复的数据,数据库会直接报错,这样就能解决该问题。

使用 redis 进行解决,通过 setnx 与 setexpire 相结合,以及 watch 和 redis 的事务来达成目的。

伪代码如下

   public function testredis(){
        $redis = new \Redis();
Redis 连接到了 "127.0.0.1" 这个地址,并且使用的端口是 6379 。
        if($redis->setnx("lock",1)){
            $redis->expire("lock",5);
            $redis->watch("lock");
            $redis->multi();
            var_dump("做领券的操作");
            var_dump("领取完毕,删除这个key");
            $redis->del("lock");
            $redis->exec();
        }else{
使用 JsonService 进行返回操作,返回的结果是失败,具体是领取失败。
        }
    }

使用 setnx 进行加锁操作,同时设置锁的自动过期时间。利用 watch 来监视这个锁。通过事务,将这些操作组合在一起,使其成为一个原子性的操作。

大至说一下为什么这么做吧

设置过期时间,是因为要避免拿到锁的程序在执行过程中出现中间出错的情况,且如果没有及时解锁,程序就会进入死锁状态。因此,需要让锁自动过期。

为什么又要用事务来操作呢?

上面的锁 5 秒会过期。程序执行完某个操作后会删除锁。如果有一个请求执行了 8 秒,到第 5 秒时锁过期,另一个请求就能抢到锁并开始执行。在第 8 秒时第一个请求会删除锁。此时要考虑它自己的锁已过期,那么它删除的锁是谁的。所以使用了事务来保证其原子性。

你可能想看:
« 上一篇
下一篇 »

相关推荐

php实时推送,php实地培训

2026年10月05日

55阅读

php乱码出现问号的原因,php乱码出现问号的原因有哪些

2026年10月05日

46阅读

php一句话木马,一句话木马ctf

2026年10月05日

49阅读

php获取数组长度,php中如何获取数组的长度

2026年10月05日

51阅读

php面试题库及答案,php程序员面试真题库

2026年10月05日

49阅读

phpcontent-type修改,php源码二次修改需要多少钱

2026年10月05日

44阅读