yii2配置redis哨兵集群,主从变化自动切换

3 篇文章 0 订阅
2 篇文章 0 订阅

yii2配置redis哨兵集群,主从变化自动切换

1.redis的哨兵模式

redis的哨兵模式,在主服务器挂掉后,会通过选举将对应的从服务器切换为主服务器,以此来达到服务的高可用性。
在业务层面如果主从做了切换可能相对应的服务器IP地址会发生改变,这样会带来程序的的正常运行。
为了不影响其业务,会考虑使用VIP去实现IP的飘逸,但是在部分情况下,虚拟机并不支持VIP,这样就无法保证业务的正常运行。所以在此情况下,通过业务本身来实现连接新的主的IP。

2.封装一个类

<?php
/**
 * Created by PhpStorm.
 * User: tianzhendong
 * Date: 2020/10/10
 * Time: 9:32 AM
 */

namespace library\redis;


use yii\base\Exception;

class SentinelRedis
{
    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) {
            $redis = $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;
    }
}

3.配置哨兵ip列表 params.php

return [
    'sentinelAddr'=>[
        ['host' => '127.0.0.1','port'=> 26378],
        ['host' => '127.0.0.1','port'=> 26379]
    ],
    ];

4.业务获取最新主服务器redis对象

		use library\redis\SentinelRedis;

		$hosts = Yii::$app->params['sentinelAddr'];
        $masterName = 'mymaster';
        $sredis = new SentinelRedis($hosts, $masterName);
        $masterRedis = $sredis->getInstansOf();
        var_dump($masterRedis->rawcommand('ROLE'));

5.运行(配置了主为7001,从为7002、7003)

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值