下单实现分布式锁

最近一直在优化下单部分,今天优化了一下redis的加锁方式。

为了防止每个下单用户重复点击而造成二次提交,在下单的时候会给每个用户加一把锁。

加锁代码实现:

$result = redis()->set($key, Context::get('request_id'), ['nx', 'ex' => 10])
return $result;

这个地方使用了nx属性,当不存在的时候才会设置,如果存在的话,就会设置失败。

设置的值为一个请求的track_id,整个请求的生命周期这个track_id都会是一样的。后面会说设置成追踪id的作用。

这个地方不可以先setnx值,然后在expire对应的key,因为这是两条 Redis 命令,不具有原子性,如果在 setnx 之后程序挂了,会使得锁没有设置过期时间,这样就会发生死锁定.

解锁代码实现:

$lua = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
$result = redis()->eval($lua, [$key, Context::get('request_id')], 1);

这个地方使用了lua脚本去处理解锁问题,为什么要用lua,因为要保证原子性,先判断获取的值和设置的值是否一样,然后在删除。

这地方不能简单的使用del直接去删除,因为,有可能你删除的键是别人的键,或者不同客户端生成的锁,你也给删了。这就是为什么使用请求的track_id的原因。比如说,你上个请求处理的时间太长了,锁的时间到了,自动释放了,如果不加track_id,可能将下一个请求的锁给释放掉了。

暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇