/** * @inheritdoc * @throws InvalidArgumentException * @throws LockHasAcquiredAlreadyException */ public function acquire($lockTime, $waitTime = 0, $sleep = null) { if ($lockTime < self::LOCK_MIN_TIME) { if ($this->catchExceptions) { return false; } throw new InvalidArgumentException('LockTime must be not less than ' . self::LOCK_MIN_TIME . ' sec.'); } if ($this->isAcquired) { if ($this->catchExceptions) { return false; } throw new LockHasAcquiredAlreadyException('Lock with key "' . $this->key . '" has acquired already'); } $time = microtime(true); $exitTime = $waitTime + $time; $sleep = ($sleep ?: self::LOCK_DEFAULT_WAIT_SLEEP) * 1000000; do { if ($this->Redis->set($this->key, $this->token, null, $lockTime * 1000, 'NX')) { $this->isAcquired = true; return true; } if ($waitTime) { usleep($sleep); } } while ($waitTime && microtime(true) < $exitTime); $this->isAcquired = false; return false; }
/** * Safe update json in Redis storage * @param Redis $Redis * @param string $key * @param array $array * @throws Exception */ function updateJsonInRedis(RedisClient $Redis, $key, array $array) { // Create new Lock instance $Lock = new RedisLock($Redis, 'Lock_' . $key, RedisLock::FLAG_CATCH_EXCEPTIONS); // Acquire lock for 2 sec. // If lock has acquired in another thread then we will wait 3 second, // until another thread release the lock. Otherwise it throws a exception. if (!$Lock->acquire(2, 3)) { throw new Exception('Can\'t get a Lock'); } // Get value from storage $json = $Redis->get($key); if (!$json) { $jsonArray = []; } else { $jsonArray = json_decode($json, true); } // Some operations with json $jsonArray = array_merge($jsonArray, $array); $json = json_encode($jsonArray); // Update key in storage $Redis->set($key, $json); // Release the lock // After $lock->release() another waiting thread (Lock) will be able to update json in storage $Lock->release(); }
*/ /** * Transactions */ namespace Examples; require dirname(__DIR__) . '/vendor/autoload.php'; // or require (dirname(__DIR__).'/src/autoloader.php'); use RedisClient\Pipeline\Pipeline; use RedisClient\Pipeline\PipelineInterface; use RedisClient\RedisClient; $Redis = new RedisClient(); // Example 1. Transactions $Redis->watch(['foo', 'bar']); $Redis->multi(); $Redis->set('foo', 'bar'); $Redis->set('bar', 'foo'); $result = $Redis->exec(); var_dump($result); // array(2) { // [0]=> bool(true) // [1]=> bool(true) // } // Example 2. True way to use transactions via Pipeline $result = $Redis->pipeline(function (PipelineInterface $Pipeline) { /** @var Pipeline $Pipeline */ $Pipeline->watch(['foo', 'bar']); $Pipeline->multi(); $Pipeline->set('foo', 'bar'); $Pipeline->set('bar', 'foo'); $Pipeline->exec();