• 技术文章 >后端开发 >php教程

    PHP如何基于redis的分布式锁防止高并发重复请求

    青灯夜游青灯夜游2019-11-29 15:39:49转载1075

    需求:

    我们先举个某系统验证的列子:(A渠道系统,业务B系统,外部厂商C系统)

    (1)B业务系统调用A渠道系统,验证传入的手机、身份证、姓名三要素是否一致。

    (2)A渠道系统再调用外部厂商C系统。

    (3)A渠道系统将结果返回给B业务系统。

    这3个过程中,(2)过程,调用外部厂商是需要计费的。

    当B业务系统并发量很高时,有100笔相同的三要素校验,由于是相同的三要素,A渠道只要调用一次厂商即可知道结果。为了防止在某一请求还没响应结束的同时,其他请求也去调用外部系统,这个时候就需要加锁处理

    分布式锁的特点

     ● 原子性:同一时刻,只能有一个机器的一个线程得到锁;

     ● 可重入性:同一对象(如线程、类)可以重复、递归调用该锁而不发生死锁;

     ● 可阻塞:在没有获得锁之前,只能阻塞等待直至获得锁;

     ● 高可用:哪怕发生程序故障、机器损坏,锁仍然能够得到被获取、被释放;

     ● 高性能:获取、释放锁的操作消耗小。

    要实现:加锁,减锁,锁超时

    实现方式可以是:数据库 mc redis 系统文件 zookeeper

    我现在就是渠道系统,当100个相同的业务请求传递过来,我的第一个请求要先加锁,然后请求外部厂商系统,等响应结果以后,插入另一个key中,然后再删除锁。

    其他请求先去获取下锁,如果已经存在锁就轮寻等待,如果锁不在了,直接去查询结果。

    如果第一个请求失败了,结果并没有插入到位,就继续获取锁再去查询外部系统。

    获取锁:

    $redis->set('lock:手机号&身份证&姓名', 1, ['nx', 'ex'=>10]);

    释放锁:

    就是直接删除这个key

    锁超时:

    lock的key有超时时间

    新版的redis set命令就可以实现分布式锁,可以同时实现如果不存在时才去set和超时时间两项。


    <?php
    $redis=new Redis();
    $redis->connect("127.0.0.1",6379);
    //高并发时防止重复请求
    
    //渠道系统传递过来的key
    $lockKey='lock:18806767777&37781991111629092&taoshihan';
    $resultKey='res:18806767777&37781991111629092&taoshihan';
    
    //如果已经查询过值,可以直接返回
    $info=$redis->get($resultKey);
    if($info){
        exit($info);
    }
    
    //如果没有值的,获取锁
    $lock=$redis->set($lockKey, 1, ['nx', 'ex'=>10]);
    if($lock){
        //请求外部系统获取结果,比如响应结果比较慢
        sleep(8);
        $info='{"name":"taoshihan"}';
        $ret=$redis->set($resultKey,$info);
        if($ret){
            //删除锁
            $redis->del($lockKey);
            exit($info);
        }
    }
    echo "请稍后重试!";

    推荐学习:PHP教程

    以上就是PHP如何基于redis的分布式锁防止高并发重复请求的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:cnblogs,如有侵犯,请联系admin@php.cn删除
    专题推荐:PHP redis
    上一篇:PHP如何操作Cookie? 下一篇:PHP字符逃逸导致的对象注入详解
    大前端线上培训班

    相关文章推荐

    • 如何设定php简写功能• PhpStorm中配置SVN详解• PHP 如何处理金额• PHPStorm怎么配置喜欢的主题(图文详解)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网