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

PHP分布式锁与应用场景

PHP分布式锁与应用场景

分布式锁在多个进程同时操作共享资源时很有用。Redis是实现分布式锁的常用工具。今天说说PHP中分布式锁的实现。

Redis的SET NX实现锁。

```php
class RedisDistributedLock
{
private Redis $redis;
private string $prefix = 'lock:';
private int $defaultTimeout = 10;

public function __construct(Redis $redis)
{
$this->redis = $redis;
}

public function acquire(string $key, int $timeout = null): ?string
{
$timeout = $timeout ?? $this->defaultTimeout;
$lockKey = $this->prefix . $key;
$token = bin2hex(random_bytes(16));

$result = $this->redis->set($lockKey, $token, ['NX', 'EX' => $timeout]);
return $result ? $token : null;
}

public function release(string $key, string $token): bool
{
$lockKey = $this->prefix . $key;

$script = '
if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
else
return 0
end
';

return (bool)$this->redis->eval($script, [$lockKey, $token], 1);
}

public function synchronized(string $key, callable $callback, int $timeout = null): mixed
{
$token = $this->acquire($key, $timeout);
if ($token === null) {
throw new RuntimeException("无法获取锁: $key");
}

try {
return $callback();
} finally {
$this->release($key, $token);
}
}
}

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$lock = new RedisDistributedLock($redis);

try {
$lock->synchronized('order:123', function () {
echo "处理订单123\n";
sleep(1);
});
} catch (RuntimeException $e) {
echo "获取锁失败: {$e->getMessage()}\n";
}
?>

数据库实现乐观锁。

```php
class OptimisticLock
{
private PDO $pdo;

public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}

public function updateWithLock(int $id, array $data, callable $updateFn): bool
{
$maxAttempts = 3;

for ($i = 0; $i < $maxAttempts; $i++) {
$stmt = $this->pdo->prepare("SELECT * FROM products WHERE id = ?");
$stmt->execute([$id]);
$product = $stmt->fetch();

if (!$product) throw new RuntimeException("商品不存在");

$newData = $updateFn($product);

$stmt = $this->pdo->prepare("
UPDATE products SET stock = ?, version = version + 1
WHERE id = ? AND version = ?
");
$stmt->execute([$newData['stock'], $id, $product['version']]);

if ($stmt->rowCount() > 0) return true;
usleep(100000);
}

throw new RuntimeException("更新失败,数据已被其他进程修改");
}
}
?>

分布式锁的应用场景。

```php
// 防止重复下单
function placeOrder(PDO $pdo, Redis $redis, int $userId, int $productId): void
{
$lockKey = "order:{$userId}:{$productId}";
$lock = new RedisDistributedLock($redis);

$lock->synchronized($lockKey, function () use ($pdo, $userId, $productId) {
$stmt = $pdo->prepare("SELECT COUNT(*) FROM orders WHERE user_id = ? AND product_id = ? AND created_at > DATE_SUB(NOW(), INTERVAL 1 MINUTE)");
$stmt->execute([$userId, $productId]);
if ($stmt->fetchColumn() > 0) {
throw new RuntimeException("请勿重复下单");
}
$pdo->prepare("INSERT INTO orders (user_id, product_id) VALUES (?, ?)")->execute([$userId, $productId]);
});
}

// 定时任务防重复执行
function runUniqueTask(string $taskName, callable $task): void
{
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$lock = new RedisDistributedLock($redis);

try {
$lock->synchronized("task:{$taskName}", $task, 3600);
} catch (RuntimeException $e) {
echo "任务已在其他进程执行\n";
}
}
?>

分布式锁在需要互斥访问共享资源的场景中很有用。Redis锁实现简单性能好,但要处理锁超时和释放的问题。乐观锁通过版本号解决冲突,适合读多写少的场景。

http://www.gsyq.cn/news/1488337.html

相关文章:

  • 别再死记硬背了!用这5个真实项目案例,帮你彻底搞懂软件工程导论的核心概念
  • PN5190 NFC评估板从零上手:硬件配置、软件调试与射频优化全攻略
  • PN7160 NFC控制器硬件集成与软件移植实战指南
  • HC08微控制器SCI串口通信:输入时钟与波特率配置详解
  • 2023电赛E题STM32F1嵌入式工程:CAN通信+伺服控制+完整驱动与算法实现
  • 绝区零自动化助手:从日常任务到高阶挑战的完整解决方案
  • GNSS软件接收机调试指南:如何用MATLAB的plotTracking.m可视化分析跟踪环路性能
  • 单文件MATLAB版SGP4轨道解算工具:支持TLE输入、任意时刻外推与时间点插值
  • GPT 智能交互效果与能力边界实测
  • 魔兽争霸3优化工具:让你的经典游戏在现代电脑上焕发新生
  • 别再只记Payload了!从302跳转原理到Gopher协议,彻底搞懂SSRF本地请求伪造
  • 制造业图纸数据安全现状与防护体系建设
  • Playnite游戏库管理器:一站式整合20+平台与模拟器的终极解决方案
  • 2026 东莞实力代理记账公司推荐:广东万创实力标杆 合规财税、进出口退税、内账外包服务、注册公司正规专业财税服务优选榜单 - 变量人生001
  • 基于LPC5528与NxH3670的无线游戏手柄OTA升级实战指南
  • 利用NXP i.MX RT1010 FlexIO模块模拟I2S接口实现音频数据传输
  • i.MX 8平台DDR ECC实战:原理、性能影响与工程优化指南
  • C++模板用多了编译报错?手把手教你用CMake跨平台解决MSVC/GCC的bigobj问题
  • 2026 天津黄金回收市场摸底,本地靠谱回收排行清单 - 奢侈品回收评测
  • 用Python手把手实现卷积码的维特比硬判决译码(附完整代码与网格图动画)
  • 图解+代码:5分钟搞懂ShuffleNet的‘通道混洗’到底在洗什么(PyTorch实现)
  • 深入解析Sigma-Delta ADC:从游标卡尺原理到高精度设计实战
  • Fusion360个人版用户必看:如何巧妙利用本地存档突破10个在线模型限制
  • 抚州工厂与实体店如何挑选 GEO 公司?五大核心筛选标准 - GrowthUME
  • UE4SS终极指南:5分钟搭建虚幻引擎游戏Mod开发环境
  • 别再只增删改查了!用Neo4j的Cypher语法玩转复杂关系查询(实战案例解析)
  • 告别臃肿:Win11Debloat让你的Windows 11轻装上阵 [特殊字符]
  • 上海劳力士回收哪家靠谱?多家正规门店报价实测对比 - 奢侈品回收评测
  • 如何在UE5中高效集成3D角色:VRM模型的完整解决方案
  • GetQzonehistory:守护你的数字青春,5分钟永久备份QQ空间所有记忆