Home > Enterprise >  PHPRedis and Locking
PHPRedis and Locking

Time:12-29

I got the following two functions that I use to lock a Redis key. 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.

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. 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();

    }

CodePudding user response:

The locking is working fine. It's just the code between the locking that is crashing and causing the lock not to be released :-)

CodePudding user response:

First of all, PHP isn't async script language as JS f.e. 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.

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. So you're not performing concurrent write by calling your script.

  • Related