Redis高可用调试
背景:因为要让redis高可用,我们使用了redis双机热备(一台主机一台备机)
架构:虚拟IP=>nginx=>redis(双机)
测试
当我们使用nginx的双机热备模式,主节点挂掉之后,所有的请求会转发到从节点,这个时候我们的主节点故障恢复了,所有新的请求都会跑到主节点上。(当时我以为可以打卡下班了)
但是当我进行模拟测试,首先正常情况主机在运行中非常完美没有出现任何bug,然后我手速飞快啊,将主节点redis挂掉从节点redis自己也很自觉的接盘,然后平台还是没有bug我好难受呀,就当我信心满满的时候将主节点redis恢复,我漫不经心的看了一下平台数据,第一眼看都是正常的,但是第二眼就看到了bug,怎么我平台的数据一会显示几分钟之前的数据,一会显示正常的数据呢????
排错
一开始真的是一头雾水,因为我使用redis管理工具连接虚拟IP查看的时候都是正常的,没有出现一会正常,一会不正常的问题。
自己不断的重现和排除中,我发现从机的redis客户端连接数并没有减少,只有新的客户端连接存在于主节点redis上面,这个时候想起了自己使用的是CsRedis插件管理redis的,CsRedis使用了线程池管理redis连接。
问题
现在问题就是因为主节点Redis恢复之后,虽然重新接管平台,但是因为旧的客户端连接在从机Redis,当我们使用CsRedis的线程池中的客户端写入数据就有问题了,如果刚好拿到了主节点连接没有问题,但是刚好拿到了从节点连接写入数据就有问题了,因为从节点Redis数据无法同步到主节点。(因为只有从Redis会fork一个线程同步主Redis的数据)
解决思路
- 编写一个接口手动释放CsRedis中的线程池,让它重新获取客户端连接。
- 因为无法准确的知道,什么时候释放。暂时不使用。
- 使用Redis哨兵模式,解决Redis数据不同步的问题。
- 因为没有找到nginx一定转发到主节点(因为哨兵会随机选举主节点,最主要问题就是公司底层采集不支持哨兵模式)
- 定时获取主节点Redis运行状态,如果主节点Redis运行正常就将从节Redis重启,达到redis连接释放。
- 这种方式代码修改的最少,那就是它吧。
说干就干
我们可以每隔一段时间通过telnet判断主机是否存活,如果存活就先关闭从机redis,然后60秒之后进行重启。
func_timing_redis(){
# 获取主机redis运行情况
path_deploy=$(echo|telnet 主机IP 6379)
# 判断是否正常
is_start=$([[ $path_deploy =~ "Escape character is '^]" ]] && echo "0")
# 获取是否需要重启
if [ $is_start -eq 0 ] ;then
cur_dateTime="`date +%Y-%m-%d,%H:%m:%s`"
# 停止容器
docker stop redis;
sleep 60;
docker start redis;
echo "$cur_dateTime :重启成功"
fi
}
func_timing_redis
Shell中的定时任务 crontab(记得定时清理你的日志文件)
crondtab是 下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,crondtab进程每分钟会定期检查是否有要执行的任务,如果有要执行的任务,则自动执行该任务。
我们只需要执行crontab -e命令,就可以将自己编写好的shell脚本设置为定时任务了。
查看我们的定时任务crontab -l命令
日志是一定要有的