php 防止高并发批量入库的解决方法

9 篇文章 0 订阅

最近项目有个类似于签到的功能,功能上线后出现一位用户疯狂刷签到的问题;我们功能正常没问题,由于用户模拟了高并发的场景,所以数据库中出现了很多同时插入的数据;在来回检查代码,和数据库之后才终于解决了问题;

1.出现相同数据的原因
因为同一时间内过来的请求很多,并且这些请求间隔都是毫秒级,它们同时通过了对数据重复判断的条件,所以同时插入了很多数据
2.我的解决办法
我用了文件锁的思路:使用非阻塞的文件排他锁,用了之后继续观察了几天也没在有重复数据了,并且我升级我们接口的验证规则,防止再有利用接口重复请求的情况

  $fp = fopen(PUBLIC_PATH.date('Y-m-d').'lock.txt', "w+");//使用非阻塞的文件排他锁,防止高并发插入多条数据
            if(!flock($fp,LOCK_EX | LOCK_NB)){  //flock() 函数锁定或释放文件。
              $this->jsonError('','系统繁忙,签到失败,请刷新后重试!');
            }            
            
           //用户当天签到的数据
  

           if($todayData['isign'] == 1){
                 //已签到         
              
           }else{
           	/**此区域有bug,高并发会同时插入很多数据**/
                // 无今天数据
                if($todayData == NULL){
              
                }else{
       		//签到成功
                  flock($fp,LOCK_UN);//释放锁
                       
                }else{
                
                  $this->jsonError('','签到失败,请刷新后重试!');
                }

以上是项目遇到的问题,进行的记录,接下来总结一下再遇到这样的问题解决的方法.

一般遇到类似秒杀,批量入库的操作解决方法,就是加锁和队列,锁可以学习一下悲观和乐观锁,文件锁,队列就redis的就ok;

1.悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。
2. 使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据
3. 对于日IP不高或者说并发数不是很大的应用,一般不用考虑这些!用一般的文件操作方法完全没有问题。但如果并发高,在我们对文件进行读写操作时,很有可能多个进程对进一文件进行操作,如果这时不对文件的访问进行相应的独占,就容易造成数据丢失
4. 直接将请求放入队列中的,采用FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值