Exemplo n.º 1
0
	/**
	 * Get a Redis object with a connection suitable for fetching the specified key
	 * @return Array (server, RedisConnRef) or (false, false)
	 */
	protected function getConnection( $key ) {
		if ( count( $this->servers ) === 1 ) {
			$candidates = $this->servers;
		} else {
			$candidates = $this->servers;
			ArrayUtils::consistentHashSort( $candidates, $key, '/' );
			if ( !$this->automaticFailover ) {
				$candidates = array_slice( $candidates, 0, 1 );
			}
		}

		foreach ( $candidates as $server ) {
			$conn = $this->redisPool->getConnection( $server );
			if ( $conn ) {
				return array( $server, $conn );
			}
		}
		return array( false, false );
	}
Exemplo n.º 2
0
 /**
  * Get a Redis object with a connection suitable for fetching the specified key
  * @param string $key
  * @return array (server, RedisConnRef) or (false, false)
  */
 protected function getConnection($key)
 {
     $candidates = array_keys($this->serverTagMap);
     if (count($this->servers) > 1) {
         ArrayUtils::consistentHashSort($candidates, $key, '/');
         if (!$this->automaticFailover) {
             $candidates = array_slice($candidates, 0, 1);
         }
     }
     while (($tag = array_shift($candidates)) !== null) {
         $server = $this->serverTagMap[$tag];
         $conn = $this->redisPool->getConnection($server);
         if (!$conn) {
             continue;
         }
         // If automatic failover is enabled, check that the server's link
         // to its master (if any) is up -- but only if there are other
         // viable candidates left to consider. Also, getMasterLinkStatus()
         // does not work with twemproxy, though $candidates will be empty
         // by now in such cases.
         if ($this->automaticFailover && $candidates) {
             try {
                 if ($this->getMasterLinkStatus($conn) === 'down') {
                     // If the master cannot be reached, fail-over to the next server.
                     // If masters are in data-center A, and slaves in data-center B,
                     // this helps avoid the case were fail-over happens in A but not
                     // to the corresponding server in B (e.g. read/write mismatch).
                     continue;
                 }
             } catch (RedisException $e) {
                 // Server is not accepting commands
                 $this->handleException($conn, $e);
                 continue;
             }
         }
         return array($server, $conn);
     }
     $this->setLastError(BagOStuff::ERR_UNREACHABLE);
     return array(false, false);
 }
Exemplo n.º 3
0
 /**
  * @return Status Uses RediConnRef as value on success
  */
 protected function getConnection()
 {
     if (!isset($this->conn)) {
         $conn = false;
         $servers = $this->ring->getLocations($this->key, 3);
         ArrayUtils::consistentHashSort($servers, $this->key);
         foreach ($servers as $server) {
             $conn = $this->pool->getConnection($this->serversByLabel[$server], $this->logger);
             if ($conn) {
                 break;
             }
         }
         if (!$conn) {
             return Status::newFatal('pool-servererror', implode(', ', $servers));
         }
         $this->conn = $conn;
     }
     return Status::newGood($this->conn);
 }
Exemplo n.º 4
0
 /**
  * Get the server index and table name for a given key
  * @param string $key
  * @return array Server index and table name
  */
 protected function getTableByKey($key)
 {
     if ($this->shards > 1) {
         $hash = hexdec(substr(md5($key), 0, 8)) & 0x7fffffff;
         $tableIndex = $hash % $this->shards;
     } else {
         $tableIndex = 0;
     }
     if ($this->numServers > 1) {
         $sortedServers = $this->serverNames;
         ArrayUtils::consistentHashSort($sortedServers, $key);
         reset($sortedServers);
         $serverIndex = key($sortedServers);
     } else {
         $serverIndex = 0;
     }
     return array($serverIndex, $this->getTableNameByShard($tableIndex));
 }
Exemplo n.º 5
0
 /**
  * Get a Redis object with a connection suitable for fetching the specified key
  * @param string $key
  * @return array (server, RedisConnRef) or (false, false)
  */
 protected function getConnection($key)
 {
     $candidates = array_keys($this->serverTagMap);
     if (count($this->servers) > 1) {
         ArrayUtils::consistentHashSort($candidates, $key, '/');
         if (!$this->automaticFailover) {
             $candidates = array_slice($candidates, 0, 1);
         }
     }
     foreach ($candidates as $tag) {
         $server = $this->serverTagMap[$tag];
         $conn = $this->redisPool->getConnection($server);
         if ($conn) {
             return array($server, $conn);
         }
     }
     $this->setLastError(BagOStuff::ERR_UNREACHABLE);
     return array(false, false);
 }
Exemplo n.º 6
0
 /**
  * Get a Redis object with a connection suitable for fetching the specified key
  * @param string $key
  * @return array (server, RedisConnRef) or (false, false)
  */
 protected function getConnection($key)
 {
     $candidates = array_keys($this->serverTagMap);
     if (count($this->servers) > 1) {
         ArrayUtils::consistentHashSort($candidates, $key, '/');
         if (!$this->automaticFailover) {
             $candidates = array_slice($candidates, 0, 1);
         }
     }
     foreach ($candidates as $tag) {
         $server = $this->serverTagMap[$tag];
         $conn = $this->redisPool->getConnection($server);
         if (!$conn) {
             continue;
         }
         try {
             $info = $conn->info();
             // Check if this server has an unreachable redis master
             if ($info['role'] === 'slave' && $info['master_link_status'] === 'down' && $this->automaticFailover) {
                 // If the master cannot be reached, fail-over to the next server.
                 // If masters are in data-center A, and slaves in data-center B,
                 // this helps avoid the case were fail-over happens in A but not
                 // to the corresponding server in B (e.g. read/write mismatch).
                 continue;
             }
         } catch (RedisException $e) {
             // Server is not accepting commands
             $this->handleException($conn, $e);
             continue;
         }
         return array($server, $conn);
     }
     $this->setLastError(BagOStuff::ERR_UNREACHABLE);
     return array(false, false);
 }