当前位置: 首页 > news >正文

PHP模拟高并发异步请求测试+redis的setnx处理并发和防止死锁处理

/** PHP并发异步请求测试*  /test/curlMulti*/public function curlMultiAction(){$urls = ["http://localhost:801/api/order/create","http://localhost:801/api/order/create","http://localhost:801/api/order/create","http://localhost:801/api/order/create","http://localhost:801/api/order/create", "http://localhost:801/api/order/create",];//并发测试$url = 'http://localhost:801/api/order/create';$data=['customerId'=>'10000','customerOrderNo'=>'Test530051-'.uniqid(),'goodsId'=>'1001273','account'=>'18857850025x','num'=>1,'sign'=>'abDebug',];// 创建批处理cURL句柄$multi_handle = curl_multi_init();$curls = [];foreach ($urls as $url){$ch = curl_init();$data['customerOrderNo'] = uniqid('Test-');curl_setopt($ch, CURLOPT_POST, 1);curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_multi_add_handle($multi_handle, $ch);$curls[] = $ch;}$running = null;do {curl_multi_exec($multi_handle, $running);} while ($running > 0);foreach ($curls as $ch) {$response = curl_multi_getcontent($ch);echo "Response: " . $response . PHP_EOL;curl_multi_remove_handle($multi_handle, $ch);curl_close($ch);}curl_multi_close($multi_handle);die;}在 Redis 里,所谓 SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果,不过很多人没有意识到 SETNX 有陷阱!比如说:某个查询数据库的接口,因为调用量比较大,所以加了缓存,并设定缓存过期后刷新,问题是当并发量比较大的时候,如果没有锁机制,那么缓存过期的瞬间,大量并发请求会穿透缓存直接查询数据库,造成雪崩效应,如果有锁机制,那么就可以控制只有一个请求去更新缓存,其它的请求视情况要么等待,要么使用过期的缓存。下面以目前 PHP 社区里最流行的 PHPRedis 扩展为例,实现一段演示代码:<?php$ok = $redis->setNX($key, $value);if ($ok) {$cache->update();$redis->del($key);
}?>
缓存过期时,通过 SetNX  获取锁,如果成功了,那么更新缓存,然后删除锁。看上去逻辑非常简单,可惜有问题:如果请求执行因为某些原因意外退出了,导致创建了锁但是没有删除锁,那么这个锁将一直存在,以至于以后缓存再也得不到更新。于是乎我们需要给锁加一个过期时间以防不测:<?php$redis->multi();
$redis->setNX($key, $value);
$redis->expire($key, $ttl);
$redis->exec();?>
<?php$ok = $redis->set($key, $random, array('nx', 'ex' => $ttl));if ($ok) {$cache->update();if ($redis->get($key) == $random) {$redis->del($key);}
}?>
Redis防死锁处理: $lock_key = 'locks_' . $userid;
$is_lock = $redis->setnx($lock_key , 1); // 加锁
if($is_lock == true){ // 获取锁权限// 程序逻辑处理:if ......// 释放锁$redis->del($lock_key);
}else{// 防止死锁if($redis->ttl($lock_key) == -1){$redis->expire($lock_key, 5);}return true; // 获取不到锁权限,直接返回
}

$redis->ttl设置过期时间。当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key 的剩余生存时间。

注意:在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1 。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • PINCE——Linux 原生游戏内存修改器,一款替代 Cheat Engine 的强大游戏修改器,Linux 游戏玩家必备神器!
  • 【论文学习与撰写】论文中公式的编辑,Mathtype的使用,全文编号排版,智能截图识别公式,公式编号自动更新
  • 一键更换Linux优质的软件源和docker源 —— 筑梦之路
  • 超全MySQL优化清单
  • 如何在ThinkPHP6中轻松实现WebSocket通信?看这里就够了!
  • 【HarmonyOS NEXT星河版开发学习】综合测试案例-各平台评论部分
  • 【javaEE进阶1】spring简介IoC
  • 都2024年了,还在问网络安全怎么入门,气得我当场脑血栓发作
  • Java面试八股之如何保证消息队列中消息不重复消费
  • 如何处理前端项目中的SEO优化:从SPA到SSR与SSG
  • 车辆类型检测算法、车辆类型源码及其样本与模型解析
  • 测绘程序设计|VisualStudio2017的安装与配置|修改字体|插件推荐
  • 高性能web服务器详解
  • Flink程序部署与提交
  • redis入门
  • 2017 前端面试准备 - 收藏集 - 掘金
  • 78. Subsets
  • CentOS7简单部署NFS
  • css属性的继承、初识值、计算值、当前值、应用值
  • ES学习笔记(12)--Symbol
  • js 实现textarea输入字数提示
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • Spring Cloud Feign的两种使用姿势
  • win10下安装mysql5.7
  • 警报:线上事故之CountDownLatch的威力
  • 使用 QuickBI 搭建酷炫可视化分析
  • 智能网联汽车信息安全
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • 从如何停掉 Promise 链说起
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​​​​​​​​​​​​​​Γ函数
  • ### RabbitMQ五种工作模式:
  • #include到底该写在哪
  • (11)MATLAB PCA+SVM 人脸识别
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (层次遍历)104. 二叉树的最大深度
  • (几何:六边形面积)编写程序,提示用户输入六边形的边长,然后显示它的面积。
  • (佳作)两轮平衡小车(原理图、PCB、程序源码、BOM等)
  • (每日一问)操作系统:常见的 Linux 指令详解
  • (十三)Maven插件解析运行机制
  • (未解决)macOS matplotlib 中文是方框
  • (转) ns2/nam与nam实现相关的文件
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • .net6使用Sejil可视化日志
  • .Net--CLS,CTS,CLI,BCL,FCL
  • .NET中的Exception处理(C#)
  • .vimrc 配置项
  • @Documented注解的作用
  • [ 渗透工具篇 ] 一篇文章让你掌握神奇的shuize -- 信息收集自动化工具
  • [10] CUDA程序性能的提升 与 流
  • [2]十道算法题【Java实现】
  • [20171106]配置客户端连接注意.txt
  • [Android实例] 保持屏幕长亮的两种方法 [转]
  • [BSidesCF 2019]Kookie1