新聞中心
從Redis官方路線圖來看,大概會(huì)在Redis3.0左右正式支持Cluster。不過即便是樂觀的估計(jì),至少也得等幾個(gè)月的時(shí)間,為了讓我的應(yīng)用在這段時(shí)間內(nèi)能保持高可用性,我以主從服務(wù)器為基礎(chǔ)實(shí)現(xiàn)了一個(gè)Failover過渡方案。

在大余等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都做網(wǎng)站、網(wǎng)站制作 網(wǎng)站設(shè)計(jì)制作按需網(wǎng)站策劃,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),營(yíng)銷型網(wǎng)站建設(shè),外貿(mào)營(yíng)銷網(wǎng)站建設(shè),大余網(wǎng)站建設(shè)費(fèi)用合理。
從理論上解釋,一旦主服務(wù)器下線,可以在從服務(wù)器里挑選出新的主服務(wù)器,同時(shí)重新設(shè)置主從關(guān)系,并且當(dāng)下線服務(wù)器重新上線后能自動(dòng)加入到主從關(guān)系中去,內(nèi)容如下:
$nodes) {
foreach ($nodes as $node) {
$node = new RedisNode($node['host'], $node['port']);
if ($node->isValid()) {
$this->config[$name][] = $node;
}
}
if (empty($this->config[$name])) {
throw new Exception('Invalid config.');
}
$this->map[$name] = $this->config[$name][0];
}
if (file_exists(self::MAP_FILE)) {
$map = include self::MAP_FILE;
foreach ((array)$map as $name => $node) {
$node = new RedisNode($node['host'], $node['port']);
$this->map[$name] = $node;
}
}
}
public function run()
{
$set_nodes_master = function($nodes, $master) {
foreach ($nodes as $node) {
$node->setMaster($master->host, $master->port);
}
};
foreach ($this->config as $name => $nodes) {
$is_master_valid = false;
foreach ($nodes as $node) {
if ($node == $this->map[$name]) {
$is_master_valid = true;
break;
}
}
if ($is_master_valid) {
$set_nodes_master($nodes, $this->map[$name]);
continue;
}
foreach ($nodes as $node) {
$master = $node->getMaster();
if (empty($master)) {
continue;
}
if ($master['master_host'] != $this->map[$name]->host) {
continue;
}
if ($master['master_port'] != $this->map[$name]->port) {
continue;
}
if ($master['master_sync_in_progress']) {
continue;
}
$node->clearMaster();
$set_nodes_master($nodes, $node);
$this->map[$name] = $node;
break;
}
}
$map = array();
foreach ($this->map as $name => $node) {
$map[$name] = array(
'host' => $node->host, 'port' => $node->port
);
}
$content = '';
file_put_contents(self::MAP_FILE, $content);
}
}
class RedisNode
{
public $host;
public $port;
const CLI = '/usr/local/bin/redis-cli';
public function __construct($host, $port)
{
$this->host = $host;
$this->port = $port;
}
public function setMaster($host, $port)
{
if ($this->host != $host || $this->port != $port) {
return $this->execute("SLAVEOF {$host} {$port}") == 'OK';
}
return false;
}
public function getMaster()
{
$result = array();
$this->execute('INFO', $rows);
foreach ($rows as $row) {
if (preg_match('/^master_/', $row)) {
list($key, $value) = explode(':', $row);
$result[$key] = $value;
}
}
return $result;
}
public function clearMaster()
{
return $this->execute('SLAVEOF NO ONE') == 'OK';
}
public function isValid()
{
return $this->execute('PING') == 'PONG';
}
public function execute($command, &$output = null)
{
return exec(
self::CLI . " -h {$this->host} -p {$this->port} {$command}", $output
);
}
}
?>其中提到了兩個(gè)文件,先說一下config.php:
array(
array('host' => '192.168.0.1', 'port' => '6379'),
array('host' => '192.168.0.2', 'port' => '6379'),
array('host' => '192.168.0.3', 'port' => '6379'),
),
);
?>說明:每個(gè)別名對(duì)應(yīng)一組服務(wù)器,在這組服務(wù)器中,有一個(gè)是主服務(wù)器,其余都是從服務(wù)器,主從關(guān)系不要在配置文件里硬編碼,而應(yīng)該通過SLAVEOF命令動(dòng)態(tài)設(shè)定。
再說一下map.php文件,內(nèi)容如下:
array (
'host' => '192.168.0.1', 'port' => '6379'
),
);
?>說明:別名對(duì)應(yīng)的是當(dāng)前有效的服務(wù)器。需要注意的是這個(gè)文件是自動(dòng)生成的!程序在使用Redis的時(shí)候,都配置成別名的形式,具體的host,port通過此文件映射獲得。
明白了以上代碼之后,運(yùn)行就很簡(jiǎn)單了:
run(); ?>
說明:實(shí)際部署時(shí),最嚴(yán)格的方式是以守護(hù)進(jìn)程的方式來執(zhí)行,不過如果要求不是很苛刻的話,CRON就夠了。測(cè)試時(shí)可以手動(dòng)殺掉主服務(wù)器進(jìn)程,再通過INFO查看效果。
再補(bǔ)充一些命令行用法的相關(guān)說明,本文都是使用redis-cli來發(fā)送命令的,通常這也是最佳選擇,不過如果因?yàn)槟承┰虿荒苁褂胷edis-cli的話,也可以使用nc(netcat)命令按照Redis協(xié)議實(shí)現(xiàn)一個(gè)簡(jiǎn)單的客戶端工具,比如說PING命令可以這樣實(shí)現(xiàn):
shell> (echo -en "PING\r\n"; sleep 1) | nc localhost 6379
說明:之所以需要sleep一下是因?yàn)镽edis的請(qǐng)求響應(yīng)機(jī)制是Pipelining方式的。
既然說到這里了,就再嘮十塊錢兒的,通常,我們可以使用telnet命令和服務(wù)交互,但是telnet有一點(diǎn)非常不爽的是命令行不支持上下鍵歷史,還好可以借助rlwrap來達(dá)成這個(gè)目的,視操作系統(tǒng),可以很容易的用APT或YUM來安裝,運(yùn)行也很簡(jiǎn)單:
shell> rlwrap telnet localhost 6379
說明:通過使用rlwrap,不僅支持上下鍵歷史,而且連Ctrl+r搜索也一并支持了,強(qiáng)!
…
在Redis Cluster釋出前,希望這個(gè)腳本能幫到你,其實(shí)其他的服務(wù)也可以使用類似的方案,比如MySQL,不過復(fù)雜性會(huì)加大很多,好在已經(jīng)有類似MHA之類的方案了。
【編輯推薦】
- 緩存大量小文件?Redis是首選!
- Redis能干啥?細(xì)看11種Web應(yīng)用場(chǎng)景
- 主流NoSQL數(shù)據(jù)庫之Redis全面評(píng)測(cè)
本文題目:Redis高可用性之Failover過渡方案
分享URL:http://www.dlmjj.cn/article/cogojsj.html


咨詢
建站咨詢
