redis的哨兵模式,在主服务器挂掉后,会通过选举将对应的从服务器切换为主服务器,以此来达到服务的高可用性。
在业务层面如果主从做了切换可能相对应的服务器IP地址会发生改变,这样会带来程序的的正常运行。为了不影响其业务,会考虑使用VIP去实现IP的飘逸,但是在部分情况下,虚拟机并不支持VIP,这样就无法保证业务的正常运行。索引在此情况下,通过业务本身来实现连接新的主的IP。本文主要以PHP为例,相关代码如下
<?php
class SRedis
{
/**
* 哨兵地址,支持多哨兵地址
* @var array
* eg: [ [ 'host' => '127.0.0.1' , 'port' => 26379 ] ]
*/
private $_sentinelAddr = [];
private $_sentinelConn = null;
private $_timeout = 10; //超时时间
private $_masterName = 'mymaster'; //主节点名称
private static $_handle = []; //存放redis连接实例
public function __construct(array $iplist, string $masterName = null)
{
$this->_sentinelAddr = $iplist;
$masterName !== null && $this->_masterName = $masterName;
$this->_getSentinelConn();
}
/**
* 获取redis主节点的实例
* @return bool|Redis
* @throws Exception
*/
public function getInstansOf()
{
$masterInfo = $this->getMasterInfo();
if ($masterInfo) {
$instansof = $this->_connection($masterInfo[0], $masterInfo[1], $this->_timeout);
return $instansof;
}
return false;
}
/**
* 获取主节点的ip地址
* @return array
*/
public function getMasterInfo()
{
$masterInfo = [];
if ($this->_sentinelConn != null) {
$masterInfo = $this->_sentinelConn->rawcommand("sentinel", 'get-master-addr-by-name', $this->_masterName);
}
return $masterInfo;
}
/**
* 设置哨兵连接句柄
*/
private function _getSentinelConn()
{
if (is_array($this->_sentinelAddr) && $this->_sentinelAddr) {
$this->_sentinelConn = $this->_RConnect($this->_sentinelAddr);
}
}
/**
* 获取redis句柄(如果是多主机,保证连接的是可用的哨兵服务器)
* @param array $hosts
* @return null|Redis
*/
private function _RConnect(array $hosts)
{
$count = count($hosts);
$redis = null;
if ($count == 1) {
$this->_connection($hosts[0]['host'], $hosts[0]['port'], $this->_timeout);
} else {
$i = 0;
while ($redis == null && $i < $count) {
$redis = $this->_connection($hosts[$i]['host'], $hosts[$i]['port'], $this->_timeout);
$i++;
}
}
return $redis;
}
/**
* redis 连接句柄
* @param string $host
* @param int $port
* @param int $timeout
* @return null|Redis
*/
private function _connection(string $host, int $port, int $timeout)
{
if (isset(self::$_handle[$host . ':' . $port])) {
return self::$_handle[$host . ':' . $port];
}
try {
$redis = new Redis();
$redis->connect($host, $port, $timeout);
self::$_handle[$host . ':' . $port] = $redis;
} catch (Exception $e) {
$redis = null;
}
return $redis;
}
}
$hosts = [
[
'host' => '127.0.0.1',
'port' => 26381
],
[
'host' => '127.0.0.1',
'port' => 26380
]
];
$masterName = 'mymaster';
$sredis = new SRedis($hosts, $masterName);
$masterRedis = $sredis->getInstansOf();
if ($masterRedis) {
print_r($masterRedis->hgetall("iplist"));
} else {
echo "redis 服务器连接失败";
}
以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要
PHP进阶架构师>>>视频、面试文档免费获取docs.qq.com![ab1df08bb952ff35d334d157b6401ebf.png](https://i-blog.csdnimg.cn/blog_migrate/942f4af632d064c752e735b327c44ab4.jpeg)
或 者关注咱们下面的知乎专栏
PHP架构师圈子zhuanlan.zhihu.com![a6fd49b6ea5f8a9166e1f45c43f07711.png](https://i-blog.csdnimg.cn/blog_migrate/a9f00ca9bd8a109b6b858efc0908b6ad.jpeg)
原文来源:https://www.cnblogs.com/tm2015/p/11313434.html