简体   繁体   English

PHPRedis 和锁定

[英]PHPRedis and Locking

I got the following two functions that I use to lock a Redis key.我得到了以下两个用于锁定 Redis 密钥的函数。 I am trying to prevent concurrency execution of a block of code using Redis. So what I do is use the following functions in such a way that they prevent the execution of the same code by different threads.我试图阻止使用 Redis 并发执行一段代码。所以我所做的是以这样一种方式使用以下函数,它们阻止不同线程执行相同的代码。

lockRedisKey("ABC");
CODE THAT I DON'T WANT TO RUN CONCURRENTLY!
unlockRedisKey("ABC");

Unfortunately, it doesn't seem to work and causes an infinitely loop at lockRedisKey() until exit_time is reached.不幸的是,它似乎不起作用并导致 lockRedisKey() 无限循环,直到达到 exit_time。 What could be wrong?有什么问题吗?

  static public function lockRedisKey($key, $value = "true") {

        $redis = RedisClient::getInstance();

        $time = microtime(true);
        $exit_time = $time + 10;
        $sleep = 10000;

        do {

            // Lock Redis with PX and NX

            $lock = $redis->setnx("lock:" . $key, $value);

            if ($lock == 1) {
                $redis->expire("lock:" . $key, "10");
                return true;
            }

            usleep($sleep);

        } while (microtime(true) < $exit_time);

        return false;

    }

    static public function unlockRedisKey($key) {

        $redis = RedisClient::getInstance();

        $redis->del("lock:" . $key);

    }

I'm aware that I might be facing deadlocks, so I decided to use transactions, but I continue to face the issue.我知道我可能会遇到死锁,所以我决定使用事务,但我仍然面临这个问题。


    static public function lockRedisKey($key, $value = "true") {

        $redis = RedisClient::getInstance();

        $time = microtime(true);
        $exit_time = $time + 10;
        $sleep = 10000;

        do {

            // Lock Redis with PX and NX

            $redis->multi();
            $redis->set('lock:' . $key, $value, array('nx', 'ex' => 10));
            $ret = $redis->exec();

            if ($ret[0] == true) {
                return true;
            }

            usleep($sleep);

        } while (microtime(true) < $exit_time);

        return false;

    }

    static public function unlockRedisKey($key) {

        $redis = RedisClient::getInstance();

        $redis->multi();
        $redis->del("lock:" . $key);
        $redis->exec();

    }

The locking is working fine.锁定工作正常。 It's just the code between the locking that is crashing and causing the lock not to be released:-)这只是崩溃和导致锁不被释放的锁定之间的代码:-)

First of all, PHP isn't async script language as JS fe You haven't any control on the script execution ordering, so it means you can't run code that below lockRedisKey() call in concurent way.首先, PHP 不是 JS fe 那样的异步脚本语言,您无法控制脚本执行顺序,因此这意味着您无法以并发方式运行lockRedisKey()调用下方的代码。

I assume you're not completely understand what usleep function is actually doing, it's just delay process and not postpone it, so it just blocks process for $sleep time and after this continue script execution.我假设您不完全理解usleep function 实际上在做什么,它只是延迟进程而不是推迟它,所以它只是阻止进程$sleep时间,然后继续执行脚本。 So you're not performing concurrent write by calling your script.所以你不是通过调用你的脚本来执行并发写入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM