本文将介绍如何使用PHP来连接redis哨兵模式。哨兵模式:大概的原理就是监听redis主库心跳包,如果心跳断开,则枚举一个从库推举成为新的主库,防止redis宕机不能使用。为了增强redis的性能,防止其挂掉,引用redis哨兵监控redis集群是个不错的选择。下面三步简单记录php连接redis哨兵。 第一步、获取哨兵模式连接redis句柄对象
/**
* 哨兵模式连接redis
* @return array|Redis
*/
function im_cache_redis() {
global $_W;
static $im_redisobj;
$config = $_W['config']['im']['redis'];
//哨兵节点
$temp_data = [
[
'ip' => '192.168.101.85',
'port' => 26380
],
[
'ip' => '192.168.101.85',
'port' => 26381
],
[
'ip' => '192.168.101.85',
'port' => 26382
]
];
$address = redis_nodeinfo($temp_data);
logging_run(__METHOD__ . ':redis哨兵获取主节点地址:' . json_encode($address),LOGGING_INFO);
$im_redisobj = new Redis();
try {
$im_redisobj->connect($address['ip'],intval($address['port']));
if (!empty($config['auth'])) {
$auth = $im_redisobj->auth($config['auth']);
}
} catch (Exception $e) {
logging_run(__METHOD__ . ':redis连接失败,错误信息:' . $e->getMessage(),LOGGING_ERROR);
return error(-1,'im redis连接失败,错误信息:'.$e->getMessage());
}
return $im_redisobj;
}
第二步、获取redis哨兵主节点地址
/**
* 获取redis哨兵主节点地址
* @param array $temp_data
* @return array
*/
function redis_nodeinfo($temp_data = []){
$random = [];
$ips = [];
//哨兵节点
//$temp_data = [['ip'=>'101.36.149.73','port'=>263719],['ip'=>'101.36.149.41','port'=>26379],['ip'=>'101.36.149.189','port'=>26379]];
for($count=1;$count<count($temp_data);$count++){
$random[] =$count;
}
shuffle($random);
foreach($random as $key){
$ips[$temp_data[$key]['ip']]=['port'=>$temp_data[$key]['port']];
}
$sentinel = new Sentinel();
foreach($ips as $ip=>$portinfo){
try{
$sentinel->connect($ip, $portinfo['port'],1);
$address = $sentinel->getMasterAddrByName('mymaster');
if($address){
echo '哨兵节点:' .$ip .'正常'. '<br/>';
return $address;
}
}catch(Exception $e){
echo '哨兵节点:' .$ip .'异常 异常信息:' . $e->getMessage() . '<br/>';
}
}
}
第三步、封装Sentinel类
<?php
class Sentinel
{
/**
* @var \Redis
*/
protected $redis;
public function __construct()
{
$this->redis = new Redis();
}
public function __destruct()
{
try {
$this->redis->close();
} catch (\Exception $e) {
}
}
/**
* @param $host
* @param int $port
* @return boolean
*/
public function connect($host, $port = 26379)
{
if (!$this->redis->connect($host, $port)) {
return false;
}
return true;
}
/**
* This command simply returns PONG.
*
* @return string STRING: +PONG on success. Throws a RedisException object on connectivity error.
*/
public function ping()
{
return $this->redis->ping();
}
/**
* Show a list of monitored masters and their state.
*
* @return array
*/
public function masters()
{
return $this->parseArrayResult($this->redis->rawCommand('SENTINEL', 'masters'));
}
/**
* parse redis response data
*
* @param array $data
* @return array
*/
private function parseArrayResult(array $data)
{
$result = array();
$count = count($data);
for ($i = 0; $i < $count;) {
$record = $data[$i];
if (is_array($record)) {
$result[] = $this->parseArrayResult($record);
$i++;
} else {
$result[$record] = $data[$i + 1];
$i += 2;
}
}
return $result;
}
/**
* Show the state and info of the specified master.
*
* @param string $master_name
* @return array
*/
public function master($master_name)
{
return $this->parseArrayResult($this->redis->rawCommand('SENTINEL', 'master', $master_name));
}
/**
* Show a list of slaves for this master, and their state.
*
* @param string $master_name
* @return array
*/
public function slaves($master_name)
{
return $this->parseArrayResult($this->redis->rawCommand('SENTINEL', 'slaves', $master_name));
}
/**
* Show a list of sentinel instances for this master, and their state.
*
* @param string $master_name
* @return array
*/
public function sentinels($master_name)
{
return $this->parseArrayResult($this->redis->rawCommand('SENTINEL', 'sentinels', $master_name));
}
/**
* Return the ip and port number of the master with that name.
* If a failover is in progress or terminated successfully
* for this master it returns the address and port of the promoted slave.
*
* @param string $master_name
* @return array
*/
public function getMasterAddrByName($master_name)
{
$data = $this->redis->rawCommand('SENTINEL', 'get-master-addr-by-name', $master_name);
return array(
'ip' => $data[0],
'port' => $data[1]
);
}
/**
* This command will reset all the masters with matching name.
* The pattern argument is a glob-style pattern.
* The reset process clears any previous state in a master
* (including a failover in progress), and removes every slave
* and sentinel already discovered and associated with the master.
*
* @param string $pattern
* @return int
*/
public function reset($pattern)
{
return $this->redis->rawCommand('SENTINEL', 'reset', $pattern);
}
/**
* Force a failover as if the master was not reachable,
* and without asking for agreement to other Sentinels
* (however a new version of the configuration will be published
* so that the other Sentinels will update their configurations).
*
* @param string $master_name
* @return boolean
*/
public function failOver($master_name)
{
return $this->redis->rawCommand('SENTINEL', 'failover', $master_name) === 'OK';
}
/**
* @param string $master_name
* @return boolean
*/
public function ckquorum($master_name)
{
return $this->checkQuorum($master_name);
}
/**
* Check if the current Sentinel configuration is able to
* reach the quorum needed to failover a master, and the majority
* needed to authorize the failover. This command should be
* used in monitoring systems to check if a Sentinel deployment is ok.
*
* @param string $master_name
* @return boolean
*/
public function checkQuorum($master_name)
{
return $this->redis->rawCommand('SENTINEL', 'ckquorum', $master_name);
}
/**
* Force Sentinel to rewrite its configuration on disk,
* including the current Sentinel state. Normally Sentinel rewrites
* the configuration every time something changes in its state
* (in the context of the subset of the state which is persisted on disk across restart).
* However sometimes it is possible that the configuration file is lost because of
* operation errors, disk failures, package upgrade scripts or configuration managers.
* In those cases a way to to force Sentinel to rewrite the configuration file is handy.
* This command works even if the previous configuration file is completely missing.
*
* @return boolean
*/
public function flushConfig()
{
return $this->redis->rawCommand('SENTINEL', 'flushconfig');
}
/**
* This command tells the Sentinel to start monitoring a new master with the specified name,
* ip, port, and quorum. It is identical to the sentinel monitor configuration directive
* in sentinel.conf configuration file, with the difference that you can't use an hostname in as ip,
* but you need to provide an IPv4 or IPv6 address.
*
* @param $master_name
* @param $ip
* @param $port
* @param $quorum
* @return boolean
*/
public function monitor($master_name, $ip, $port, $quorum)
{
return $this->redis->rawCommand('SENTINEL', 'monitor', $master_name, $ip, $port, $quorum);
}
/**
* is used in order to remove the specified master: the master will no longer be monitored,
* and will totally be removed from the internal state of the Sentinel,
* so it will no longer listed by SENTINEL masters and so forth.
*
* @param $master_name
* @return boolean
*/
public function remove($master_name)
{
return $this->redis->rawCommand('SENTINEL', 'remove', $master_name);
}
/**
* The SET command is very similar to the CONFIG SET command of Redis,
* and is used in order to change configuration parameters of a specific master.
* Multiple option / value pairs can be specified (or none at all).
* All the configuration parameters that can be configured via sentinel.conf
* are also configurable using the SET command.
*
* @param $master_name
* @param $option
* @param $value
* @return boolean
*/
public function set($master_name, $option, $value)
{
return $this->redis->rawCommand('SENTINEL', 'set', $master_name, $option, $value);
}
/**
* get last error
*
* @return string
*/
public function getLastError()
{
return $this->redis->getLastError();
}
/**
* clear last error
*
* @return boolean
*/
public function clearLastError()
{
return $this->redis->clearLastError();
}
/**
* sentinel server info
*
* @return string
*/
public function info()
{
return $this->redis->info();
}
}
本文转自 https://www.100txy.com/article/261,如有侵权,请联系删除。