当前位置: 首页 > 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 。

http://www.lryc.cn/news/427473.html

相关文章:

  • 访问网站出现“此站点不安全”如何解决
  • 同一台电脑同时连接使用Gitee(码云)和Github
  • GORM 插入和批量插入操作介绍
  • 企业CAD图纸加密软件推荐!2024年好用的10款CAD图纸加密软件排行
  • 智能电梯标志新时代:墨水屏电子标签引领变革
  • 使用nvm下载nodejs版本报错
  • 深入理解CSS的:valid和:invalid伪类:增强表单验证的艺术
  • 稚晖君发布5款全能人形机器人,开源创新,全能应用
  • 【总结】冲击偶的概念与性质
  • Hbase图形化界面
  • PhalApi:在宝塔一键安装部署PHP开源接口框架的教程
  • 什么是BERT?工程快速入门
  • SQL - 事务
  • 系统, 安装完以后只能进ubuntu
  • 闲鱼功能全解析:闲置物品快速变现
  • 牛客网SQL进阶129 :月均完成试卷数不小于3的用户
  • Astro + Cloudflare Pages 快速搭建个人博客
  • Vue中<style scoped>与<style module>的深入解析与应用
  • Qt系列之数据库(二)代码篇
  • @RequstParam@PathVariable@RequestBody的区别
  • Maven继承和聚合特性
  • python opencv实时视频输入
  • 为什么头文件不能写using namespace
  • 使用 preloadRouteComponents 提升 Nuxt 应用的性能
  • mybatisPlus的@TableLogic逻辑删除注解导致联合索引失效的坑
  • C# 隐式转换和显式转换
  • 入门网络安全工程师要学习哪些内容
  • 深入理解 Go 并发原语
  • 计算机毕业设计选题推荐-springboot 基于springboot的宠物健康顾问系统
  • 数据结构—— 初识二叉树