配置文件:

port 26379 //哨兵端口号
daemonize yes //守护进程
pidfile "/usr/local/redis-sentinel/redis_sentinel_26379.pid" //pid目录
logfile "/usr/local/redis-sentinel/redis_sentinel_26379.log" //log目录
dir  /usr/local/redis-sentinel //运行目录
sentinel monitor master_6379 127.0.0.1 6379 2  //自定义主节点名称、HOST、PORT、2票则认为主死(一般设置为哨兵节点数的一半+1)
sentinel down-after-milliseconds master_6379 30000 //失联30秒后则认定节点出问题
sentinel parallel-syncs master_26379 1 //在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步,设置过多会造成redis主节点压力变大
sentinel failover-timeout master_6379 180000 //故障中每个阶段的最长超时时间
sentinel deny-scripts-reconfig yes //不允许使用SENTINEL SET设置notification-script和client-reconfig-script
sentinel auth-path master_6379 why
port 26380
daemonize yes
pidfile "/usr/local/redis-sentinel/redis_sentinel_26380.pid"
logfile "/usr/local/redis-sentinel/redis_sentinel_26380.log"
dir  /usr/local/redis-sentinel
sentinel monitor master_6379 127.0.0.1 6379 2
sentinel down-after-milliseconds master_6379 30000
sentinel parallel-syncs master_6379 1
sentinel failover-timeout master_6379 180000
sentinel deny-scripts-reconfig yes 
sentinel auth-path master_6379 why
port 26381
daemonize yes
pidfile "/usr/local/redis-sentinel/redis_sentinel_26381.pid"
logfile "/usr/local/redis-sentinel/redis_sentinel_26381.log"
dir  /usr/local/redis-sentinel
sentinel monitor master_6379 127.0.0.1 6379 2
sentinel down-after-milliseconds master_6379 30000
sentinel parallel-syncs master_6379 1
sentinel failover-timeout master_6379 180000
sentinel deny-scripts-reconfig yes 
sentinel auth-path master_6379 why

运行:

redis-sentinel /usr/local/redis_sentinel/redis_sentinel_conf

运行后的配置文件:

port 26379
daemonize yes
pidfile "/usr/local/redis-sentinel/redis_sentinel_26379.pid"
logfile "/usr/local/redis-sentinel/redis_sentinel_26379.log"
dir "/usr/local/redis-sentinel"
sentinel myid b65bc8d309545ce496ae749cc7ebd2baed1e8e09
sentinel deny-scripts-reconfig yes
sentinel monitor master_6379 127.0.0.1 6379 2
sentinel config-epoch master_6379 0
sentinel leader-epoch master_6379 0
# Generated by CONFIG REWRITE
sentinel known-sentinel master_6379 127.0.0.1 26380 7f961871e2bce4d7e80e6bf0157614543fc8c92e
sentinel known-sentinel master_6379 127.0.0.1 26381 139b6932dea1161c71c643abf29f26f1a3a4088c
sentinel current-epoch 0

登录客户端:

redis-cli -p 26379

客户端API命令:

  • info:查看守护信息
  • sentinel masters:获取所有被监控的主节点信息
  • sentinel master master_6379:获取某个主节点信息
  • sentinel slaves:获取所有被监控从节点信息
  • sentinel slaves master_6379:获取某个从节点信息
  • sentinel get-master-addr-by-name master_6379:获取指定master name主节点的IP和port
  • sentinel reset master_6379:对指定主节点的配置进行重置,包含清楚主节点的相关状态,重新发现从节点和sentinel节点
  • sentinel failover master_6379:对指定主节点进行强制故障转移,转移完成后其他sentinel节点按照转移结果更新自身配置
  • sentinel ckquorum master_6379:检测当前可用sentinel节点个数是否满足quorum个数
  • sentinel flushconfig:将当前sentinel配置强制刷到磁盘上,用于配置文件丢失情况
  • sentinel remove master_6379:取消当前sentinel节点对指定master节点的监控
  • sentinel monitor master_6379 127.0.0.1 6379 2:添加当前sentinel节点对指定master节点的监控
  • sentinel set master_6379 quorum 2:动态修改sentinel节点配置
  • sentinel is-master-down-by-addr:sentinel节点之间用来交换对主节点是否下线的判断,根据参数的不同,还可以作为sentinel领导者选举的通信方式。

注意:

sentinel通过监视主节点,执行info replaction命令,从而获得并监视相应的从节点

一般一个主节点需要开启3个sentinel守护,则修改配置文件的主机地址、端口号即可。

一个sentinel可守护多个主节点

 

主节点出故障后,会推举出新的主节点,然后自动将新主节点配置文件的replicaof去掉,其他从节点的replicaof改为新的主节点,

replica-read-only 不改变,所以旧的从节点仍然只读,但新的主节点由去掉了replicaof配置,所以即使replica-read-only为yes,仍可作为主节点写入。

结论:主节点出故障后,将replica-read-only改为yes,重启即可,replicaof项都会被sentinel自动更改

 

PHP客户端实现:

<?php

class Sentinel
{
    private $connection;

    public function __construct()
    {
        $this->connection = [];
    }

    private function connect($host, $port)
    {
        try {
            $con = new Redis();
            $res = $con->connect($host, $port);

            if ($res) {
                return $con;
            }
        } catch (Exception $exception) {
            echo "error hosts:" . $host . " port:" . $port . "\n";
        }
        return false;
    }

    public function setSentinel($host, $port)
    {
        $res = $this->connect($host, $port);

        if ($res) {
            $this->connection[] = $res;

            return true;
        }
        return false;
    }

    public function getSentinel()
    {
        if (empty($this->connection)) {
            throw new ErrorException("sorry no connection");
        }
        $masterList = [];
        foreach ($this->connection as $con) {

            $result = $con->rawCommand('SENTINEL', 'masters');

            list(, , , $host, , $port) = $result[0];

            $masterList[] = [$host, $port];

        }
        return $masterList;
    }

    public function getMaster()
    {
        $list = $this->getSentinel();
        return $list[0];
    }

    public function getConnection()
    {
        list($host, $port) = $this->getMaster();

        return $this->connect($host, $port);
    }

}

$sentinel = new Sentinel();
$sentinel->setSentinel('127.0.0.1',26379);
$sentinel->setSentinel('127.0.0.1',26380);
$sentinel->setSentinel('127.0.0.1',26381);

//获取redis主服务配置
$cfg = $sentinel->getMaster();
print_r($cfg);

$conn = $sentinel->getConnection();

//查看连接是否正常
print_r($conn->ping());

 

相关原理和概念:http://www.redis.cn/topics/sentinel.html