龙行博客

走路看风景,经历看人生,岁月留痕迹,人生留轨迹,17的历史,18的豪情,时间的匆忙,人生的风景,放开心胸往前走,成功再远行,放开理想往前走,梦想再行动。
现在位置:首页 > 编程语言 > PHP > 基于redis的分布式锁防止高并发重复请求

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

龙行    PHP    2020-8-6    126    0评论    

需求:


我们先举个某系统验证的列子:(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 "请稍后重试!";


评论一下 分享本文 赞助站长

赞助站长X

扫码赞助站长
联系站长
龙行博客
  • 版权申明:此文如未标注转载均为本站原创,自由转载请表明出处《龙行博客》。
  • 本文网址:https://www.liaotaoo.cn/373.html
  • 上篇文章:唉!到底是转还是不转呢?
  • 下篇文章:用户密码输错N次,自动锁定
  • redis php7
挤眼 亲亲 咆哮 开心 想想 可怜 糗大了 委屈 哈哈 小声点 右哼哼 左哼哼 疑问 坏笑 赚钱啦 悲伤 耍酷 勾引 厉害 握手 耶 嘻嘻 害羞 鼓掌 馋嘴 抓狂 抱抱 围观 威武 给力
提交评论

清空信息
关闭评论
快捷导航
联系博主
在线壁纸
给我留言
四四五五
音乐欣赏
返回顶部