php方案 Redis Sentinel故障转移
·
<?php
/**
* Redis Sentinel 完整实现 - 自动故障转移
*/
class RedisSentinelClient {
private $sentinels;
private $masterName;
private $redis;
private $timeout = 2;
public function __construct($sentinels, $masterName = 'mymaster') {
$this->sentinels = $sentinels; // [['host' => '127.0.0.1', 'port' => 26379], ...]
$this->masterName = $masterName;
$this->connect();
}
/**
* 连接到当前主节点
*/
private function connect() {
$master = $this->getMaster();
if (!$master) {
throw new Exception('无法获取主节点信息');
}
$this->redis = new Redis();
$this->redis->connect($master['ip'], $master['port'], $this->timeout);
}
/**
* 从 Sentinel 获取主节点信息
*/
private function getMaster() {
foreach ($this->sentinels as $sentinel) {
try {
$s = new RedisSentinel($sentinel['host'], $sentinel['port'], $this->timeout);
$master = $s->getMasterAddrByName($this->masterName);
if ($master && count($master) >= 2) {
return ['ip' => $master[0], 'port' => $master[1]];
}
} catch (Exception $e) {
continue; // 尝试下一个 Sentinel
}
}
return null;
}
/**
* 执行 Redis 命令(带自动重连)
*/
public function execute($method, $args = []) {
$maxRetries = 3;
$attempt = 0;
while ($attempt < $maxRetries) {
try {
return call_user_func_array([$this->redis, $method], $args);
} catch (RedisException $e) {
$attempt++;
if ($attempt >= $maxRetries) {
throw $e;
}
// 重新连接到新的主节点
sleep(1);
$this->connect();
}
}
}
/**
* 魔术方法:代理所有 Redis 方法
*/
public function __call($method, $args) {
return $this->execute($method, $args);
}
/**
* 获取集群状态
*/
public function getClusterInfo() {
foreach ($this->sentinels as $sentinel) {
try {
$s = new RedisSentinel($sentinel['host'], $sentinel['port']);
return [
'master' => $s->master($this->masterName),
'slaves' => $s->slaves($this->masterName),
'sentinels' => $s->sentinels($this->masterName)
];
} catch (Exception $e) {
continue;
}
}
return null;
}
}
// ============ 使用示例 ============
// 配置 Sentinel 节点
$sentinels = [
['host' => '127.0.0.1', 'port' => 26379],
['host' => '127.0.0.1', 'port' => 26380],
['host' => '127.0.0.1', 'port' => 26381]
];
// 创建客户端
$redis = new RedisSentinelClient($sentinels, 'mymaster');
// 使用 Redis(自动故障转移)
try {
$redis->set('key', 'value');
echo $redis->get('key') . "\n";
// 获取集群信息
$info = $redis->getClusterInfo();
print_r($info);
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
}
sentinel.conf - 最短配置
port 26379
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
更多推荐

所有评论(0)