当前位置: 移动技术网 > IT编程>数据库>MongoDB > Redis SETNX实现分布式锁

Redis SETNX实现分布式锁

2019年08月23日  | 移动技术网IT编程  | 我要评论

战狼2完整版迅雷,欢迎show,早教论坛

1、某进程1执行 setnx lock 以尝试获取锁

2、由于某进程2已获得了锁,所以进程1执行 setnx lock 返回0,即获取锁失败

3、进程1执行 get lock 来检测锁是否已超时,如果没超时,则线程等待一段时间,再次检测

4、如果进程1检测到锁已超时,即当前的时间大于键 lock 的值,进程1会执行以下操作

getset lock <current unix timestamp + lock timeout + 1>

5、由于 getset 操作在设置键的值的同时,还会返回键的旧值,通过比较键 lock 的旧值是否小于当前时间,可以判断进程是否已获得锁

6、假如另一个进程3也检测到锁已超时,并在进程1之前执行了 getset 操作,那么进程1的 getset 操作返回的是一个大于当前时间的时间戳,这样进程1就不会获得锁而继续等待。注意到,即使进程1接下来将键 lock 的值设置了比进程3设置的更大的值也没影响。

另外,值得注意的是,在进程释放锁,即执行 del lock 操作前,需要先判断锁是否已超时。如果锁已超时,那么锁可能已由其他进程获得,这时直接执行 del lock 操作会导致把其他进程已获得的锁释放掉。

c# code

using system;
using system.threading;
using system.threading.tasks;
using csredis;

namespace redislockdemo
{
    public class csredislock
    {
        private static readonly int _lock_timeout = 40;
        private static readonly string _lock_key = "lock";
        public static void test()
        {
            var rds = new csredisclient("127.0.0.1:6379,password=123456,defaultdatabase=13,poolsize=50,ssl=false");
            redishelper.initialization(rds);

            parallel.for(0, 13, x =>
            {
                if (getlock(_lock_key))
                {
                    console.writeline($"person:{x},线程id:{thread.currentthread.managedthreadid},获得锁 woking");

                    if (datetimeoffset.now.tounixtimemilliseconds() < redishelper.get<long>(_lock_key))
                    {
                        //释放锁
                        redishelper.del(_lock_key);
                    }
                }
                else
                {
                    console.writeline($"person:{x},线程id:{thread.currentthread.managedthreadid},获取锁异常");
                }
            });
            console.writeline();
        }

        private static bool getlock(string key)
        {
            bool getlocked = false;
            try
            {
                while (!getlocked)
                {
                    var now = datetimeoffset.now.tounixtimemilliseconds();
                    var lock_time = now + _lock_timeout + 1;
                    getlocked = redishelper.setnx(key, lock_time);
                    //判断是否获取锁,
                    if (getlocked || now > redishelper.get<long>(key) && now > redishelper.getset<long>(key, lock_time))
                    {
                        getlocked = true;
                    }
                    else
                    {
                        thread.sleep(30);
                    }
                }
            }
            catch (exception ex)
            {
                console.writeline(ex.message);
            }
            return getlocked;
        }
    }
}

相关文档:

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网