为什么很多人用keepalived来实现redis故障转移
- 目前,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故障转移的更多相关文章
- MySQL 高可用:mysql+Lvs+Keepalived 负载均衡及故障转移
系统信息: mysql主库 mysql从库 VIP 192.168.1.150 mysql 主主同步都设置 auto-increment-offset,auto-increment-increment ...
- 很多人都搞不清楚C语言和C++的关系!今天我们来一探究竟为大家解惑~
最近,身边有许多小伙伴已经开始学习编程了,但是呢,学习又会碰到许多的问题,其中作为新手小白提到最多的问题就是编程语言的选择. 每次遇到这种问题,看起来很简单,但是又有很多小伙伴搞不清编程语言之间的关系 ...
- 上传伪技术~很多人都以为判断了后缀,判断了ContentType,判断了头文件就真的安全了。是吗?
今天群里有人聊图片上传,简单说下自己的经验(大牛勿喷) 0.如果你的方法里面是有指定路径的,记得一定要过滤../,比如你把 aa文件夹设置了权限,一些类似于exe,asp,php之类的文件不能执行,那 ...
- 很多人都在埋怨没有遇到好的团队,但好的团队不可能凭空出现,一流的团队不能仅靠团队成员努力,作为Leader,要有可行的规划,并坚定地执行、时势地调整(转)
<西游记>中的唐僧团队历经千难万险,终于求得真经,目标明确.分工合理为这支队伍最终走向成功奠定了基础.唐僧从一开始,就为这个团队设定了西天取经的目标,虽然经历各种挫折与磨难,但目标从未动摇 ...
- 神贴真开眼界:为什么很多人倡导重视能力和素质,但同时对学历有严格要求?——代表了上一场比赛的输赢,招聘成本很重要。如果上一场游戏失败了,尽量让自己成为当前群体的尖子。学历只是其中的一个作品而已,但学历代表了学生时代为之做出的牺牲。人群自有偏向集中性 good
对于软件工程师职位,没学历没关系,如果真觉得自己才高八斗,请在简历里附上 github项目链接或者 appstore/google play上你的作品.如果学历比别人低,那么想必是把时间和精力用在了其 ...
- 我来科普一下为毛很多人升级了20M的电信光纤宽带反而感觉速度更卡了
下载(在线看视频,看网页,下载游戏这类都是属于下载类应用) 为毛很多人升级20M光纤更慢了呢? 因为电信对你的上传速度做了手脚, 8M以及以上家用光纤宽带全部上传限速到100KB/s 也就是1M带宽 ...
- 很多人以为 connect 和 disconnect 应该像 new 和 delete 一样成对出现 这是错误的(只要 sender 或 receiver 其中之一不存在了,connect 会自动失效。QObject::connect 函数是线程安全的)
其实我写文章也是边查资料边编辑的 有时候是怕自己的阐述不严谨,有时候是怕自己重复造轮子 就像有些人不停的教大家QLabel QDialog QWidget 个人是不屑的 命令模式 用 Qt's Und ...
- keepalived+nginx+tomcat+redis实现负载均衡和session共享(原创)
keepalived+nginx+tomcat+redis实现负载均衡和session共享 直接上链接,码了一天,就不再重写了,希望能帮到大家,有问题欢迎留言交流.
- 一道简单的 Java 笔试题,但值得很多人反思!
前言 面试别人,对我来说是一件新奇事,以前都是别人面试我.我清楚地知道,我在的地域与公司,难以吸引到中国的一流软件人才.所以,我特地调低了期望,很少问什么深入的技术问题,只问一些广泛的.基础的.我只要 ...
随机推荐
- memory leak at strcore.cpp
最近使用CString出现了内存泄露,后来发现是CString.GetBuffer之后没有ReleaseBuffer.
- Android 动态添加删除ExpandableListView的item的例子
这个例子可以学习到如下几点: 1.通过自定义Dialog(单独布局的xml文件进行弹出显示) 2.通过menu点击监听添加,删除view中的items 3.点击ExpandableListView中g ...
- 使用TextWatcher监听EditText变化
public class MainActivity extends AppCompatActivity { private TextView mTextView; private EditText m ...
- javascript设计模式学习之十六——状态模式
一.状态模式的定义 状态模式的关键是区分事务内部和外部的状态,事务内部状态改变往往会带来事务的行为改变. 状态模式中有意思的一点是,一般我们谈到封装,都是优先封装对象的行为,而非对象的状态.但在状态模 ...
- ORACLE 11G内存管理方式
SGA包含的组件: 组件名 说明 参数 buffer cache 存放从数据文件中读取的数据拷贝,所有用户之间是可以共享的 db_cache_size db_keep_cache_size db_re ...
- LinkedHashMap 和 LRU算法实现
个人觉得LinkedHashMap 存在的意义就是为了实现 LRU 算法. public class LinkedHashMap<K,V> extends HashMap<K,V&g ...
- 数据库执行监控,除了Profiler的方案
怎么查找库中的数据库相关信息: Select * from sys.databases; 返回字段: name(数据库名称) database_id(数据库id) .... Select sqlTex ...
- maven增加Spring
对于javax.annotation,spring某些注解要用的,比如:@Resource. 使用Maven管理基本的Spring依赖关系 Spring被设计为可高度模块化的 —— 使用Sprin ...
- mysql 插入重复值 INSERT ... ON DUPLICATE KEY UPDATE
向数据库插入记录时,有时会有这种需求,当符合某种条件的数据存在时,去修改它,不存在时,则新增,也就是saveOrUpdate操作.这种控制可以放在业务层,也可以放在数据库层,大多数数据库都支持这种需求 ...
- Centos7 安装 Nginx
Nginx有很多版本的,下面我给个链接http://nginx.org/packages/mainline/centos/7/x86_64/RPMS/ 下载对应当前系统版本的nginx包(packag ...