open(); Yii::debug("Executing Redis Command: {$name} " . var_export($params, true), __METHOD__); $redis = $this->redis; //мастер $redisCommand = strtoupper(Inflector::camel2words($name, false)); if (in_array($redisCommand, $this->redisSlaveCommands)) { if(!empty($this->slaves)) { //читаем из произвольного раба $redis = $this->slaves[array_rand($this->slaves)]; } } return $redis->{$name}(...$params); } protected function isValidServer(mixed $server): bool { return is_array($server) && isset($server['ip']) && isset($server['port']); } public function createClient(array $config): Redis { $service = $config['sentinel_service'] ?? 'mymaster'; $hosts = is_array($config['sentinel_host']) ? $config['sentinel_host'] : [$config['sentinel_host']]; foreach ($hosts as $host) { $newConfig = $config; $newConfig['sentinel_host'] = $host; $sentinel = $this->connectToSentinel($newConfig); if ($sentinel->ping()) { break; } } $master = $sentinel->master($service); if (!$this->isValidServer($master)) { throw new RedisException(sprintf("No master found for service '%s'.", $service)); } $slaves = $sentinel->slaves($service); foreach ($slaves as $slave) { if ($this->isValidServer($slave)) { //могут быть проблемв из-за большого количества подключений $this->slaves[] = parent::createClient(array_merge($config, [ 'host' => $slave['ip'], 'port' => $slave['port'], ])); } } return parent::createClient(array_merge($config, [ 'host' => $master['ip'], 'port' => $master['port'], ])); } private function connectToSentinel(array $config): RedisSentinel { $host = $config['sentinel_host'] ?? ''; $port = $config['sentinel_port'] ?? 26379; $timeout = $config['sentinel_timeout'] ?? 0.2; $persistent = $config['sentinel_persistent'] ?? null; $retryInterval = $config['sentinel_retry_interval'] ?? 0; $readTimeout = $config['sentinel_read_timeout'] ?? 0; $username = $config['sentinel_username'] ?? ''; $password = $config['sentinel_password'] ?? ''; $ssl = $config['sentinel_ssl'] ?? null; if (strlen(trim($host)) === 0) { throw new ConfigurationException('No host has been specified for the Redis Sentinel connection.'); } $auth = null; if (strlen(trim($username)) !== 0 && strlen(trim($password)) !== 0) { $auth = [$username, $password]; } elseif (strlen(trim($password)) !== 0) { $auth = $password; } if (version_compare(phpversion('redis'), '6.0', '>=')) { $options = [ 'host' => $host, 'port' => $port, 'connectTimeout' => $timeout, 'persistent' => $persistent, 'retryInterval' => $retryInterval, 'readTimeout' => $readTimeout, ]; if ($auth !== null) { $options['auth'] = $auth; } if (version_compare(phpversion('redis'), '6.1', '>=') && $ssl !== null) { $options['ssl'] = $ssl; } return new RedisSentinel($options); } if ($auth !== null) { /** @noinspection PhpMethodParametersCountMismatchInspection */ return new RedisSentinel($host, $port, $timeout, $persistent, $retryInterval, $readTimeout, $auth); } return new RedisSentinel($host, $port, $timeout, $persistent, $retryInterval, $readTimeout); } }