使用时长 使用 Symfony Lock 组件处理并发请求与竞态条件

本文深入探讨了symfony锁 通过分析`acquire()`方法的阻塞与非阻塞解决模式,演示了如何有效控制请求执行顺序或拒绝立即重复操作。此外,还详细阐述了`streamedresponse`生命景下如何正确管理锁的持续周期,确保长时间操作锁的持续周期,为开发者提供了布尔问题的实用指南。理解Symfony Lock组件与并发控制
在Web应用开发中,尤其是在Race Condition: Symfony Lock 描述:Symfony
Symfony Lock组件的核心是LockFactory,它负责创建Lock实例。每个Lock实例都与一个唯一的资源键关联。当一个请求尝试获取锁时,如果锁已被其他请求持有,则该请求的行为取决于acquire()方法的参数设置。阻塞与非阻塞式锁获取
acquire()方法是获取锁的关键,为模式:1. 阻塞式获取(默认行为)
当调用 acquire(true) 更多信息:的情况。
考虑以下控制器代码示例,它模拟了一个需要2个完成的操作:lt;?phpnamespace App\Controller;use Class LockTestController extends AbstractController{ #[Route(quot;/testquot;)] public function test(LockFactory $factory): JsonResponse { $lock = $factory-gt;createLock(quot;test_resourcequot;); // 名为quot;test_resourcequot;的锁 $startTime = microtime(true); // $acquired = microtime(true) - $startTime; if ($acquired) { // 模拟一个运行操作 sleep(2); // $lock-gt;release(); } return new JsonResponse([ quot;acquiredquot; =gt; $acquired, quot;acquireTimequot; =gt; $acquireTime // 记录获取锁耗时的时间 ]); }}}}登录后复制
使用curl命令同时发起两个请求:curl -k 'https://localhost/test' amp: curl -k 'https://localhost/test' 766}{quot;acquiredquot;:true,quot;acquireTimequot;:2.087 123990058899}登录后复制
从输出中可以看出,第一个请求获得了锁(acquireTime 接近0),并执行了2秒的sleep。它确保了立即操作的串口执行。
2.非阻塞式获取
当调用acquire(false)时,如果锁定已被其他请求持有,当前请求将不会等待,而是立即返回false。错误的。
上述控制器,将acquire()设置为非阻塞模式:PatentPal专利申请编写
AI软件来为专利申请自动生成内容13查看详情lt;?phpnamespace App\Controller;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\HttpFoundation\JsonResponse;use Symfony\Component\Lock\LockFactory;use Symfony\Component\Routing\Annotation\Route;class LockTestController extends AbstractController{ #[Route(quot;/test_non_blockingquot;)] public function testNonBlocking(LockFactory $factory): JsonResponse { $lock = $factory-gt;createLock(quot;test_resourcequot;); $startTime = microtime(true); // 尝试非阻塞式获取锁 $acquired = $lock-gt;acquire(false); // 非阻塞模式 $acquireTime = microtime(true) - $startTime; if ($acquired) { // 模拟运行操作 sleep(2); // 锁会在请求结束时自动释放 } else { // 返回 new JsonResponse([ quot;acquiredquot; =gt; false, quot;messagequot; =gt; quot;操作触发中,请勿重复提交。
quot;, quot;acquireTimequot; =gt; $acquireTime ], JsonResponse::HTTP_TOO_MANY_REQUESTS); } return new JsonResponse([ quot;acquiredquot; =gt; $acquired, quot;acquireTimequot; =gt; $acquireTime ]); }}登录后复制
再次同时发起两个curl 请求:curl -k 'https://localhost/test_non_blocking' amp;curl -k 'https://localhost/test_non_blocking'登录后复制
预期的输出会是:{quot;acquired quot;:true,quot;acquireTimequot;:0.0008120536804199219}{quot;acquiredqu ot;:false,quot;messagequot;:quot;操作触发中,请勿重复提交。quot;,quot;acquireTimeq uot;:0.0005118846893310547}登录后复制
可以看到,第一个请求成功获取了锁并开始执行,而第二个请求立即则返回 false: false: false: 阅读更多:StreamedResponse 下的锁管理
在某些特殊情况下,例如处理长时间运行的流式响应(Str eamedResponse),锁定的周期管理需要特别注意。通常,Symfony Lock 会组件在 StreamedResponse: 的流数据式生成过程才刚刚开始。这会导致生命在流式响应生成期间,锁未能按预期保持。
为了在 StreamedResponse Lock 实例传递给 StreamedResponse 的回调函数。另外,对于长时间运行的操作,还需要定期刷新锁以防止其周期。
以下是一个处理 StreamedResponse 的示例:lt;?phpnamespace App\Controller;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use { #[Route(quot;/export_dataquot;)] public function export(LockFactory $factory): Response { // //尝试非阻塞式获取锁,如果失败则拒绝请求 if (!$lock-gt;acquire(false)) { return new Response(quot;导出任务触发中,请稍后再试。
quot;, Response::HTTP_TOO_MANY_REQUESTS); } $response = new StreamedResponse(function () use ($lock) { // 这里回调函数中,$lock实例仍然有效 $lockTime = time(); // echo quot;行 quot; ($i 1) . quot;导出数据\nquot;;flush(内容); // 强制输出视图 // 锁定时间 if (time() - $lockTime gt; 10) { // $lock-gt;refresh(); $lockTime = time(); // ; } sleep(2); // 模拟数据处理延迟 } // 数据导出完成后,手动释放锁 $lock-gt;release(); error_log(quot;Lock 'data_export_lock'released at quot; . date('H:i:s')); }); $response-gt;headers-gt;set('Content-Type', 'text/plain'); // 示例设置为纯文本 // 如果没有将 $lock 传递给 StreamedResponse 的回调,锁会在此时被释放 return $response; }}登录后复制
在这个示例中:锁以 60 秒的 TTL 创建。acquire(false) $lock 实例通过 use ($lock) 每 10 秒调用 $lock-youjiankuohaophpcnrefresh() 显式调用 $lock-gt;release()释放锁,及时其他请求可以获取。即使PHP进程终止终止,锁种族在TTL结束后自动释放终止,即使秒60。
这意味着,如果你在不同的服务或控制器中通过LockFactory::createLock("resource_name")创建了两个独立的Lock Lock实例(例如通过依赖注入将锁注入实例到需要它的服务中),或者确保所有需要互斥访问的组件都通过同一个LockFactory LockFactory每次创建新的Lock实例是有效的:创建锁时可以指定一个生存时间(TTL)。这是一个重要的安全机制,处理:当 acquire(false) 返回 false 说明:联系我们:存在重复数据。因为在极少数情况下,如果两个请求在锁被释放且红色为:Symfony Lock Redis、Me mcached、数据库等)。根据应用需求和部署环境Symfony
Symfony
Symfony
Symfony Lock acquire()方法的阻塞与非阻塞模式,开发者可以有效地控制操作的执行顺序或立即拒绝重复操作。对于StreamedResponse 等特殊场景,理解锁期并采取相应的刷新策略关键。结合适当的错误处理和数据一致性检查,可以构建出更加健壮、可靠的应用程序。
以上就是使用Symfony Lock组详细内容,更多请关注乐哥常识网其他相关! cURL回调函数循环作用域redis memcached数据库应用开发大家都在看文章文章:PHP日期格式转换详解:从d/m/Y到l d F Y使用PHP和Font Awesome实现动态星星评分显示PHP-FPM Docker容器POST数据:安全密码指南 PHP/HTML代码修剪器:PHP-CS-Fixer实践指南
