目前,Redis还没有一个类似于MySQL Proxy或Oracle RAC的官方HA方案。
Redis作者有一个名为Redis Sentinel的计划 ,据称将会有监控,报警和自动故障转移三大功能,非常不错。
但可惜的是短期内恐怕还不能开发完成。
因此,如何在出现故障时自动转移是一个需要解决的问题。
通过对网上一些资料的搜索,有建议采用HAProxy或Keepalived来实现的,事实上如果是做Failover而非负载均衡的话,Keepalived的效率肯定是超过HAProxy的,所以我决定采用Keepalived的方案。
环境介绍:
Master: 10.6.1.143
Slave: 10.6.1.144
Virtural IP Address (VIP): 10.6.1.200
设计思路:
当 Master 与 Slave 均运作正常时, Master负责服务,Slave负责Standby;
当 Master 挂掉,Slave 正常时, Slave接管服务,同时关闭主从复制功能;
当 Master 恢复正常,则从Slave同步数据,同步数据之后关闭主从复制功能,恢复Master身份,于此同时Slave等待Master同步数据完成之后,恢复Slave身份。
然后依次循环。
需要注意的是,这样做需要在Master与Slave上都开启本地化策略,否则在互相自动切换的过程中,未开启本地化的一方会将另一方的数据清空,造成数据完全丢失。
下面,是具体的实施步骤:
在Master和Slave上安装Keepalived
$ sudo apt-get install keepalived
修改Master和Slave的/etc/hosts文件
$ sudo vim /etc/hosts
127.0.0.1 localhost
10.6.1.143 redis
10.6.1.144 redis-slave 默认安装完成keepalived之后是没有配置文件的,因此我们需要手动创建:
首先,在Master上创建如下配置文件:
$ sudo vim /etc/keepalived/keepalived.conf
vrrp_script chk_redis {
script "/etc/keepalived/scripts/redis_check.sh" ###监控脚本
interval 2 ###监控时间
}
vrrp_instance VI_1 {
state MASTER ###设置为MASTER
interface eth0 ###监控网卡
virtual_router_id 51
priority 101 ###权重值
authentication {
auth_type PASS ###加密
auth_pass redis ###密码
}
track_script {
chk_redis ###执行上面定义的chk_redis
}
virtual_ipaddress {
10.6.1.200 ###VIP
}
notify_master /etc/keepalived/scripts/redis_master.sh
notify_backup /etc/keepalived/scripts/redis_backup.sh
notify_fault /etc/keepalived/scripts/redis_fault.sh
notify_stop /etc/keepalived/scripts/redis_stop.sh
} 然后,在Slave上创建如下配置文件:
$ sudo vim /etc/keepalived/keepalived.conf
vrrp_script chk_redis {
script "/etc/keepalived/scripts/redis_check.sh" ###监控脚本
interval 2 ###监控时间
}
vrrp_instance VI_1 {
state BACKUP ###设置为BACKUP
interface eth0 ###监控网卡
virtual_router_id 51
priority 100 ###比MASTRE权重值低
authentication {
auth_type PASS
auth_pass redis ###密码与MASTRE相同
}
track_script {
chk_redis ###执行上面定义的chk_redis
}
virtual_ipaddress {
10.6.1.200 ###VIP
}
notify_master /etc/keepalived/scripts/redis_master.sh
notify_backup /etc/keepalived/scripts/redis_backup.sh
notify_fault /etc/keepalived/scripts/redis_fault.sh
notify_stop /etc/keepalived/scripts/redis_stop.sh
} 在Master和Slave上创建监控Redis的脚本
$ sudo mkdir /etc/keepalived/scripts
$ sudo vim /etc/keepalived/scripts/redis_check.sh
#!/bin/bash ALIVE=`/opt/redis/bin/redis-cli PING`
if [ "$ALIVE" == "PONG" ]; then
echo $ALIVE
exit 0
else
echo $ALIVE
exit 1
fi 编写以下负责运作的关键脚本:
notify_master /etc/keepalived/scripts/redis_master.sh
notify_backup /etc/keepalived/scripts/redis_backup.sh
notify_fault /etc/keepalived/scripts/redis_fault.sh
notify_stop /etc/keepalived/scripts/redis_stop.sh
因为Keepalived在转换状态时会依照状态来呼叫:
当进入Master状态时会呼叫notify_master
当进入Backup状态时会呼叫notify_backup
当发现异常情况时进入Fault状态呼叫notify_fault
当Keepalived程序终止时则呼叫notify_stop
首先,在Redis Master上创建notity_master与notify_backup脚本:
$ sudo vim /etc/keepalived/scripts/redis_master.sh
#!/bin/bash REDISCLI="/opt/redis/bin/redis-cli"
LOGFILE="/var/log/keepalived-redis-state.log" echo "[master]" >> $LOGFILE
date >> $LOGFILE
echo "Being master...." >> $LOGFILE 2>&1 echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 10.6.1.144 6379 >> $LOGFILE 2>&1
sleep 10 #延迟10秒以后待数据同步完成后再取消同步状态 echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1 $ sudo vim /etc/keepalived/scripts/redis_backup.sh
#!/bin/bash REDISCLI="/opt/redis/bin/redis-cli"
LOGFILE="/var/log/keepalived-redis-state.log" echo "[backup]" >> $LOGFILE
date >> $LOGFILE
echo "Being slave...." >> $LOGFILE 2>&1 sleep 15 #延迟15秒待数据被对方同步完成之后再切换主从角色
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 10.6.1.144 6379 >> $LOGFILE 2>&1 接着,在Redis Slave上创建notity_master与notify_backup脚本:
$ sudo vim /etc/keepalived/scripts/redis_master.sh
#!/bin/bash REDISCLI="/opt/redis/bin/redis-cli"
LOGFILE="/var/log/keepalived-redis-state.log" echo "[master]" >> $LOGFILE
date >> $LOGFILE
echo "Being master...." >> $LOGFILE 2>&1 echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 10.6.1.143 6379 >> $LOGFILE 2>&1
sleep 10 #延迟10秒以后待数据同步完成后再取消同步状态 echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1 $ sudo vim /etc/keepalived/scripts/redis_backup.sh
#!/bin/bash REDISCLI="/opt/redis/bin/redis-cli"
LOGFILE="/var/log/keepalived-redis-state.log" echo "[backup]" >> $LOGFILE
date >> $LOGFILE
echo "Being slave...." >> $LOGFILE 2>&1 sleep 15 #延迟15秒待数据被对方同步完成之后再切换主从角色
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 10.6.1.143 6379 >> $LOGFILE 2>&1 然后在Master与Slave创建如下相同的脚本:
$ sudo vim /etc/keepalived/scripts/redis_fault.sh
#!/bin/bash LOGFILE=/var/log/keepalived-redis-state.log echo "[fault]" >> $LOGFILE
date >> $LOGFILE $ sudo vim /etc/keepalived/scripts/redis_stop.sh
#!/bin/bash LOGFILE=/var/log/keepalived-redis-state.log echo "[stop]" >> $LOGFILE
date >> $LOGFILE 给脚本都加上可执行权限:
$ sudo chmod +x /etc/keepalived/scripts/*.sh
脚本创建完成以后,我们开始按照如下流程进行测试:
1.启动Master上的Redis
$ sudo /etc/init.d/redis start
2.启动Slave上的Redis
$ sudo /etc/init.d/redis start
3.启动Master上的Keepalived
$ sudo /etc/init.d/keepalived start
4.启动Slave上的Keepalived
$ sudo /etc/init.d/keepalived start
5.尝试通过VIP连接Redis:
$ redis-cli -h 10.6.1.200 INFO
连接成功,Slave也连接上来了。
role:master
slave0:10.6.1.144,6379,online
6.尝试插入一些数据:
$ redis-cli -h 10.6.1.200 SET Hello Redis
OK
从VIP读取数据
$ redis-cli -h 10.6.1.200 GET Hello
"Redis"
从Master读取数据
$ redis-cli -h 10.6.1.143 GET Hello
"Redis"
从Slave读取数据
$ redis-cli -h 10.6.1.144 GET Hello
"Redis"
下面,模拟故障产生:
将Master上的Redis进程杀死:
$ sudo killall -9 redis-server
查看Master上的Keepalived日志
$ tailf /var/log/keepalived-redis-state.log
[fault]
Thu Sep 27 08:29:01 CST 2012
同时Slave上的日志显示:
$ tailf /var/log/keepalived-redis-state.log
[master]
Fri Sep 28 14:14:09 CST 2012
Being master....
Run SLAVEOF cmd ...
OK
Run SLAVEOF NO ONE cmd ...
OK
然后我们可以发现,Slave已经接管服务,并且担任Master的角色了。
$ redis-cli -h 10.6.1.200 INFO
$ redis-cli -h 10.6.1.144 INFO
role:master
然后我们恢复Master的Redis进程
$ sudo /etc/init.d/redis start
查看Master上的Keepalived日志
$ tailf /var/log/keepalived-redis-state.log
[master]
Thu Sep 27 08:31:33 CST 2012
Being master....
Run SLAVEOF cmd ...
OK
Run SLAVEOF NO ONE cmd ...
OK
同时Slave上的日志显示:
$ tailf /var/log/keepalived-redis-state.log
[backup]
Fri Sep 28 14:16:37 CST 2012
Being slave....
Run SLAVEOF cmd ...
OK
可以发现目前的Master已经再次恢复了Master的角色,故障切换以及自动恢复都成功了。
转载

为什么很多人用keepalived来实现redis故障转移的更多相关文章

  1. MySQL 高可用:mysql+Lvs+Keepalived 负载均衡及故障转移

    系统信息: mysql主库 mysql从库 VIP 192.168.1.150 mysql 主主同步都设置 auto-increment-offset,auto-increment-increment ...

  2. 很多人都搞不清楚C语言和C++的关系!今天我们来一探究竟为大家解惑~

    最近,身边有许多小伙伴已经开始学习编程了,但是呢,学习又会碰到许多的问题,其中作为新手小白提到最多的问题就是编程语言的选择. 每次遇到这种问题,看起来很简单,但是又有很多小伙伴搞不清编程语言之间的关系 ...

  3. 上传伪技术~很多人都以为判断了后缀,判断了ContentType,判断了头文件就真的安全了。是吗?

    今天群里有人聊图片上传,简单说下自己的经验(大牛勿喷) 0.如果你的方法里面是有指定路径的,记得一定要过滤../,比如你把 aa文件夹设置了权限,一些类似于exe,asp,php之类的文件不能执行,那 ...

  4. 很多人都在埋怨没有遇到好的团队,但好的团队不可能凭空出现,一流的团队不能仅靠团队成员努力,作为Leader,要有可行的规划,并坚定地执行、时势地调整(转)

    <西游记>中的唐僧团队历经千难万险,终于求得真经,目标明确.分工合理为这支队伍最终走向成功奠定了基础.唐僧从一开始,就为这个团队设定了西天取经的目标,虽然经历各种挫折与磨难,但目标从未动摇 ...

  5. 神贴真开眼界:为什么很多人倡导重视能力和素质,但同时对学历有严格要求?——代表了上一场比赛的输赢,招聘成本很重要。如果上一场游戏失败了,尽量让自己成为当前群体的尖子。学历只是其中的一个作品而已,但学历代表了学生时代为之做出的牺牲。人群自有偏向集中性 good

    对于软件工程师职位,没学历没关系,如果真觉得自己才高八斗,请在简历里附上 github项目链接或者 appstore/google play上你的作品.如果学历比别人低,那么想必是把时间和精力用在了其 ...

  6. 我来科普一下为毛很多人升级了20M的电信光纤宽带反而感觉速度更卡了

    下载(在线看视频,看网页,下载游戏这类都是属于下载类应用) 为毛很多人升级20M光纤更慢了呢? 因为电信对你的上传速度做了手脚, 8M以及以上家用光纤宽带全部上传限速到100KB/s  也就是1M带宽 ...

  7. 很多人以为 connect 和 disconnect 应该像 new 和 delete 一样成对出现 这是错误的(只要 sender 或 receiver 其中之一不存在了,connect 会自动失效。QObject::connect 函数是线程安全的)

    其实我写文章也是边查资料边编辑的 有时候是怕自己的阐述不严谨,有时候是怕自己重复造轮子 就像有些人不停的教大家QLabel QDialog QWidget 个人是不屑的 命令模式 用 Qt's Und ...

  8. keepalived+nginx+tomcat+redis实现负载均衡和session共享(原创)

    keepalived+nginx+tomcat+redis实现负载均衡和session共享 直接上链接,码了一天,就不再重写了,希望能帮到大家,有问题欢迎留言交流.

  9. 一道简单的 Java 笔试题,但值得很多人反思!

    前言 面试别人,对我来说是一件新奇事,以前都是别人面试我.我清楚地知道,我在的地域与公司,难以吸引到中国的一流软件人才.所以,我特地调低了期望,很少问什么深入的技术问题,只问一些广泛的.基础的.我只要 ...

随机推荐

  1. 目标检测的图像特征提取之(一)HOG特征

    http://blog.csdn.net/liulina603/article/details/8291093

  2. 选择年份 php的写法要比js简洁一些

    所以遇到下拉框默认选择的情况,用php写比较方便一些 <select type="text" class="form-control_2" name=&q ...

  3. OC 对象和匿名对象

    OC 对象和匿名对象 对象和匿名对象的定义: 当new出一个对象时,如果用一个指针接收这个对象,那么这个指针通常被称为对象. 如果new出的对象,不用指针接收,那么这个对象就称为匿名对象. #impo ...

  4. [BS-13] 创建和注册UITableViewCell及Storyboard和Xib区别

    创建和注册UITableViewCell及Storyboard和Xib区别 // 界面创建完成被调用 - (void)viewDidLoad { [super viewDidLoad]; /** 如果 ...

  5. 解决: Fail to create empty document

    做 Programming Windows with MFC 2nd 的例子 MyWord 的时候. 发现启动的时候总是报错: Fail to create empty document. 搜索了一下 ...

  6. crsctl stat res -t 和 crsctl stat res -init -t

    11.2.0.2的grid infrastructure中crsctl stat res命令不再显示如ora.cssd.ora.ctssd.ora.diskmon等基础资源的信息.但是查看这些基础资源 ...

  7. java 笔记(5) —— 线程,yield,join

    一.线程各个状态与转换: 新建状态:用new语句创建的线程对象处于新建状态,此时它和其它的java对象一样,仅仅在堆中被分配了内存 .就绪状态:当一个线程创建了以后,其他的线程调用了它的start() ...

  8. paml正选择处理时序列里有终止密码子怎么处理掉

     先用氨基酸序列进行比对,然后追溯回核苷酸序列,根据氨基酸序列的gap进行密码子去gap,这样不会出现终止子,能最大可能的保留其生物学意义 

  9. OLTP与OLAP的差异

    OLTP与OLAP的差异 系统类型 OLTP(在线交易系统) OLAP(联机分析系统),DW(数据仓库) 数据来源 操作数据,OLTP通常是原始性数据源 联合型数据:OLAP数据来源于其他OLTP系统 ...

  10. 几个PostgreSQL数据库操作总结

    创建表 语法:如下 create table     table_name     (column_name         column_type(parametes)options,…); 注意: ...