news 2026/6/8 19:50:35

PHP分布式锁与应用场景

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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锁实现简单性能好,但要处理锁超时和释放的问题。乐观锁通过版本号解决冲突,适合读多写少的场景。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/8 19:46:01

洛雪音乐音源架构终极指南:构建跨平台无损音乐解决方案

洛雪音乐音源架构终极指南&#xff1a;构建跨平台无损音乐解决方案 【免费下载链接】lxmusic- lxmusic(洛雪音乐)全网最新最全音源 项目地址: https://gitcode.com/gh_mirrors/lx/lxmusic- 洛雪音乐lxmusic-项目为开发者提供了完整的跨平台音乐资源获取技术架构&#xf…

作者头像 李华
网站建设 2026/6/8 19:40:08

GPT-4稀疏激活机制:1.8万亿参数与2%动态路由的工程真相

1. 这不是“参数越多越好”的简单故事&#xff1a;GPT-4参数量与激活机制的真实逻辑你可能已经看到过那条刷屏的推文&#xff1a;“GPT-4有1.8万亿参数&#xff0c;但每次只用其中2%。”这句话像一颗小石子&#xff0c;砸进了大模型圈的水面&#xff0c;激起一圈又一圈的涟漪—…

作者头像 李华
网站建设 2026/6/8 19:39:25

如何用Final2x轻松实现4倍图像超分辨率:面向新手的完整指南

如何用Final2x轻松实现4倍图像超分辨率&#xff1a;面向新手的完整指南 【免费下载链接】Final2x a cross-platform image super-resolution tool 项目地址: https://gitcode.com/gh_mirrors/fi/Final2x 你是否曾经遇到过这样的情况&#xff1a;一张珍贵的照片因为分辨率…

作者头像 李华
网站建设 2026/6/8 19:38:59

HydroD新手避坑指南:从安装到第一个静水力分析(SESAM V4.10-01)

HydroD新手避坑指南&#xff1a;从安装到第一个静水力分析&#xff08;SESAM V4.10-01&#xff09;第一次打开HydroD时&#xff0c;面对密密麻麻的菜单和复杂的参数设置&#xff0c;很多新手会感到无从下手。作为海洋工程领域的重要工具&#xff0c;HydroD在船舶与浮式结构物的…

作者头像 李华
网站建设 2026/6/8 19:38:03

Linux内核学习轨迹第五部: Swap交换分区机制实现(第十一小节)

11. Swap交换分区机制实现Swap交换分区&#xff08;或交换文件&#xff09;是Linux内核的“虚拟内存扩展”&#xff0c;当系统物理内存不足时&#xff0c;内核会把不活跃的匿名页换出到swap分区&#xff0c;释放物理内存&#xff1b;当进程再次访问这些被换出的页时&#xff0c…

作者头像 李华