关于setnx实现锁
关于setnx实现锁
一、什么是Redis 的 setnx
-
Redis Setnx(SET if Not eXists) 命令在指定的 key 不存在时,为 key 设置指定的值。
-
语法
redis Setnx 命令基本语法如下:
redis 127.0.0.1:6379> SETNX KEY_NAME VALUE
- 可用版本 , >= 1.0.0
- 返回值
设置成功,返回 1 。 设置失败,返回 0
- 实例
redis> EXISTS job # job 不存在
(integer) 0
redis> SETNX job "programmer" # job 设置成功
(integer) 1
redis> SETNX job "code-farmer" # 尝试覆盖 job ,失败
(integer) 0
redis> GET job # 没有被覆盖
"programmer"
二、使用场景
两则不同业务场景下使用Redis的setnx加锁操作
1、使用Redis来实现递增编号。
-
在redis中存储了当前的编号,为了保证多线程同时获取该编号,加1操作,再写回,不会出现数据不准确的情况,使用setnx对其加锁。
-
加锁时会加上一个expire时间5000ms,在执行完对缓存中的数据操作后,会直接删除这个锁,以提高效率。
-
获取编号时,如果成功拿到锁,直接进行相应操作,如果失败,重复尝试直到成功。(获取的编号会同其他数据一道写回数据库,如果遇到redis宕机或其他情况,导致编号数据丢失,会重启后,先从数据库里把最大编号写回redis)
2、需要在后台程序中实现一个定时从数据库里找出超时数据并插入数据库中另一张表的功能。
-
我们的服务是布在三个容器上的,如果每个容器里都跑一遍超时任务,那么找出的超时数据会重复。所以我们采用setnx进行加锁。
-
定时任务的周期是1h,我们设置expire为40min(该时间一定能保证定时任务的完成),在操作完该定时任务后,不删除该锁,而是等到超时由redis删除。当定时任务去获取该key时,如果成功那么直接运行,如果失败,表示该任务正在或者已经执行,直接跳过,不会去重复尝试。
以上遇到的两种setnx实现分布式锁的情况,一个需要主动删除锁保证效率,一个不主动删除锁,保证多容器下定时任务的单次运行(定时任务间隔时长很长,可以这么干,如果时间短的话就不太适合)。
本文来自博客园,作者:ElloeStudy,转载请注明原文链接:https://www.cnblogs.com/ElloeStudy/p/16209060.html