经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » PHP » 查看文章
[PHP] 基于redis的分布式锁防止高并发重复请求
来源:cnblogs  作者:陶士涵  时间:2019/10/21 9:01:26  对本文有异议

需求:
我们先举个某系统验证的列子:(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和超时时间两项。

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

 

原文链接:http://www.cnblogs.com/taoshihan/p/11711098.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号