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锁实现简单性能好,但要处理锁超时和释放的问题。乐观锁通过版本号解决冲突,适合读多写少的场景。
PHP分布式锁与应用场景
张小明
前端开发工程师
华硕笔记本轻量控制神器G-Helper:3大场景下的终极性能优化指南
华硕笔记本轻量控制神器G-Helper:3大场景下的终极性能优化指南 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zen…
洛雪音乐音源架构终极指南:构建跨平台无损音乐解决方案
洛雪音乐音源架构终极指南:构建跨平台无损音乐解决方案 【免费下载链接】lxmusic- lxmusic(洛雪音乐)全网最新最全音源 项目地址: https://gitcode.com/gh_mirrors/lx/lxmusic- 洛雪音乐lxmusic-项目为开发者提供了完整的跨平台音乐资源获取技术架构…
GPT-4稀疏激活机制:1.8万亿参数与2%动态路由的工程真相
1. 这不是“参数越多越好”的简单故事:GPT-4参数量与激活机制的真实逻辑你可能已经看到过那条刷屏的推文:“GPT-4有1.8万亿参数,但每次只用其中2%。”这句话像一颗小石子,砸进了大模型圈的水面,激起一圈又一圈的涟漪—…
如何用Final2x轻松实现4倍图像超分辨率:面向新手的完整指南
如何用Final2x轻松实现4倍图像超分辨率:面向新手的完整指南 【免费下载链接】Final2x a cross-platform image super-resolution tool 项目地址: https://gitcode.com/gh_mirrors/fi/Final2x 你是否曾经遇到过这样的情况:一张珍贵的照片因为分辨率…
HydroD新手避坑指南:从安装到第一个静水力分析(SESAM V4.10-01)
HydroD新手避坑指南:从安装到第一个静水力分析(SESAM V4.10-01)第一次打开HydroD时,面对密密麻麻的菜单和复杂的参数设置,很多新手会感到无从下手。作为海洋工程领域的重要工具,HydroD在船舶与浮式结构物的…
Linux内核学习轨迹第五部: Swap交换分区机制实现(第十一小节)
11. Swap交换分区机制实现Swap交换分区(或交换文件)是Linux内核的“虚拟内存扩展”,当系统物理内存不足时,内核会把不活跃的匿名页换出到swap分区,释放物理内存;当进程再次访问这些被换出的页时,…