如何在Laravel中创建随服务器持续运行的商品库存更新函数
实现持续运行的库存更新逻辑
直接用while(true)死循环在应用进程里是非常不推荐的,会耗尽CPU资源,还可能导致应用无响应。下面是几种生产环境可用的方案:
方案1:定时任务(Cron/Windows任务计划)
这是最常用的方式,通过系统定时任务周期性触发库存更新脚本:
- 编写独立的PHP脚本
update_stock.php,实现核心库存更新逻辑:
<?php // 连接数据库 $db = new PDO('mysql:host=localhost;dbname=your_db', 'user', 'pass'); // 获取需要更新的商品并调整库存 $stmt = $db->prepare("UPDATE products SET quantity = quantity + :updated WHERE need_update = 1"); $stmt->execute([':updated' => $updated]); ?>
- Linux系统添加Cron任务,比如每分钟执行一次:
* * * * * php /path/to/update_stock.php
- Windows系统可通过「任务计划程序」设置定期执行该脚本。
方案2:消息队列驱动的异步处理
如果库存更新是基于事件触发(比如订单完成、补货通知),用消息队列更高效:
- 当有库存更新需求时,将任务发送到消息队列(比如Redis List)
- 编写守护进程脚本,持续监听队列并处理任务:
<?php $redis = new Redis(); $redis->connect('localhost', 6379); while (true) { // 阻塞式读取队列,避免空循环浪费CPU $task = $redis->brPop('stock_update_queue', 0); if ($task) { $data = json_decode($task[1], true); // 执行库存更新 $db = new PDO('mysql:host=localhost;dbname=your_db', 'user', 'pass'); $stmt = $db->prepare("UPDATE products SET quantity = quantity + :updated WHERE id = :product_id"); $stmt->execute([ ':updated' => $data['updated'], ':product_id' => $data['product_id'] ]); } // 可选:每次处理后短暂休眠,降低资源占用 usleep(100000); } ?>
- 用
nohup或systemd将脚本作为守护进程运行,确保服务器重启后自动恢复:
nohup php /path/to/stock_worker.php > /dev/null 2>&1 &
方案3:常驻进程框架(适合复杂场景)
如果需要更稳定的常驻进程,可使用Swoole/Workerman这类PHP协程框架:
<?php use Swoole\Timer; // 初始化Swoole进程 $worker = new Swoole\Process(function ($process) { // 每隔5秒执行一次库存更新 Timer::tick(5000, function () { // 库存更新逻辑 $db = new PDO('mysql:host=localhost;dbname=your_db', 'user', 'pass'); $stmt = $db->prepare("UPDATE products SET quantity = quantity + :updated WHERE need_update = 1"); $stmt->execute([':updated' => $updated]); }); }); $worker->start(); Swoole\Process::wait(); ?>
- 框架自带进程管理、异常重启机制,比自行编写的while循环更稳定。
核心注意事项
- 无论用哪种方案,都要添加数据库事务,避免并发更新导致库存数据不一致:
$db->beginTransaction(); try { // 库存更新操作 $db->commit(); } catch (Exception $e) { $db->rollBack(); }
- 避免在循环中重复创建数据库连接,尽量复用连接池或单例连接。
内容的提问来源于stack exchange,提问作者Marzanur Zarif
相关产品推荐
相关产品推荐

