PHP 实现 redis 分布式锁
Laiyong Wang Lv6

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php

function acquireLock($redis, $lockKey, $lockValue, $expireTime) {
// 使用 SET 命令获取锁,设置 NX 参数确保键在不存在时才会被设置,EX 参数设置过期时间
return $redis->set($lockKey, $lockValue, array('nx', 'ex' => $expireTime));
}

function releaseLock($redis, $lockKey, $lockValue) {
// 使用 Lua 脚本原子性地释放锁
$script = '
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
';
return $redis->eval($script, array($lockKey, $lockValue), 1);
}

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

$lockKey = "wanglaiyong"; // 锁的键
$lockValue = uniqid(); // 锁的唯一值
$expireTime = 10; // 锁的过期时间,单位为秒

if (acquireLock($redis, $lockKey, $lockValue, $expireTime)) {
echo "获取锁成功,正在执行代码...\n";

// 执行需要加锁的代码
sleep(5);

if (releaseLock($redis, $lockKey, $lockValue)) {
echo "释放锁成功。\n";
} else {
echo "释放锁失败。\n";
}
} else {
echo "获取锁失败。\n";
}
?>

总结

Redis 分布式锁通过 SET 命令的 NX 和 EX 参数实现获取锁的操作,确保只有在键不存在时才会设置键,并且设置键的过期时间以防止死锁。释放锁时,通过 Lua 脚本确保释放锁的操作是原子的,避免在高并发环境下发生竞态条件。

lua 脚本

在释放的时候,处理的确实比自己的做法好,借鉴了

$li-margin-bottom = 0.8rem $post-tool-button-width = 2.5rem .post-tools-container { padding-top var(--component-gap) .post-tools-list { li { margin-bottom $li-margin-bottom &:last-child { margin-bottom 0 } } li.tools-item { position relative box-sizing border-box width $post-tool-button-width height $post-tool-button-width color var(--text-color-3) font-size 1.2rem background var(--background-color-1) border-radius 50% box-shadow 2px 2px 5px var(--shadow-color) cursor pointer &:hover { box-shadow 2px 2px 8px var(--shadow-hover-color) } i { color var(--text-color-3) } &:hover { color var(--background-color-1) background var(--primary-color) i { color var(--background-color-1) !important } } &.toggle-show-toc { display none } &.go-to-comments { .post-comments-count { position absolute top 0 right -1rem display none align-items center justify-content center box-sizing border-box min-width 1.1rem height 1.1rem padding 0 0.2rem color var(--badge-color) font-size 12px background var(--badge-background-color) border-radius 0.4rem +keep-tablet() { display none !important } } } } li.status-item { width $post-tool-button-width height $post-tool-button-width color var(--text-color-3) font-size 1.6rem cursor pointer &.post-lock { cursor default .fa-lock-open { display none color var(--keep-success-color) } &.decrypt { cursor pointer .fa-lock-open { display block } .fa-lock { display none } } } } } }