基于consul的Redis高可用方案

一 前言

这几天在研究如何做Redis的高可用容灾方案,查询了资料和咨询DBA同行,了解到Redis可以基于consul和sentinel实现读写分离以及HA高可用方案。本文讲述基于consul的Redis高可用方案实践。

感谢邓亚运的提示和资料协助。

二 consul 是什么?

Consul是HashiCorp公司基于go语言研发用于服务发现和配置共享开的分布式高可用的系统。提供内服务注册与发现框架,分布一致性协议实现,健康检查,Key/Value存储,多数据中心方案,以及Web UI支持,相比于Zookeeper,Consul不再需要依赖其他工具。

Consul提供的如下关键特性:

  1. Consul采用Raft一致性协议算法来保证服务的高可用,使用GOSSIP协议管理成员和广播消息,并且支持ACL访问控制。
  2. 服务注册与发现: Consul 同时支持DNS或者HTTP两种接口进行服务注册和服务发现。
  3. 支持健康检查: Consul可以通过定期运行脚本进行健康检查,根据脚本的返回值判断机器或服务是否健康,返回值为0时才代表健康。用户可以自定义的任意shell/Python脚本进行服务(Redis/MySQL等)的健康检查,这点相比其他同类工具更灵活。值得注意的是consul中返回值0是没问题(passed),1是警告(warning),其他值是检查失败(critical)
  4. Key/Value存储: 一个用来存储动态配置的系统。提供简单的HTTP接口,可以在任何地方操作。
  5. 支持多数据中心方案:支持多机房配置,可以避免单机房单点故障,多个数据中心要求每个数据中心都要安装一组Consul cluster,多个数据中心间基于gossip protocol协议来通讯,使用Raft算法实现一致性。
  6. 简易安装部署:安装包仅包含一个二进制文件,支持跨平台(*Nix,WIN)运行。可与Docker等轻量级容器实现无缝配合。
  7. 官方提供web管理界面, etcd无此功能.

三 Consul 架构组成

Consul是分布式的高可用系统,该系统中有两种角色Server 和Client。通过启动agent时指定Server或者client模式实现Consul集群中角色划分。

Consul Server:服务端用于保存Consul Cluster的状态信息, 实现数据一致性,响应RPC请求。在局域网内与本地客户端通讯, 通过广域网与其他数据中心通讯。每个Consul Cluster的Server数量推荐为3或5个。

Consul Client:客户端,只维护自身的状态, 并将HTTP和DNS接口请求转发给服务端。

注意:

Server和Client的角色和Consul Cluster上运行的应用服务无关, 是基于Consul层面的一种角色划分。

四 Consul和同类工具的对比表

五 如何使用

环境准备

server: 10.9.51.13 
client: 10.215.20.13 10.215.20.7 10.9.141.52
  1. 下载和安装 wget "https://releases.hashicorp.com/consul/1.0.7/consul_1.0.7_linux_amd64.zip" 如果前面的特性介绍所说,consul其实就是一个二进制文件,下载以后解压放到/usr/local/bin之后就可以使用,不依赖任何东西。 cp consul /usr/local/bin/
  2. 初始化目录 mkdir /etc/consul.d/ -p && mkdir /data/consul/shell -p vim /etc/consul.d/client.json
  3. 配置文件 在server 节点 10.9.51.13 编辑配置文件 /etc/consul.d/server.json { "data_dir": "/data/consul", "datacenter": "dc1", "log_level": "INFO", "server": true, "bootstrap_expect": 1, "bind_addr": "10.9.51.13", "client_addr": "10.9.51.13", "ui":true } 在三个client节点配置文件 /etc/consul.d/client.json { "data_dir": "/data/consul", "enable_script_checks": true, "bind_addr": "10.215.20.13", "retry_join": ["10.9.51.13"], "retry_interval": "15s", "rejoin_after_leave": true, "start_join": ["10.9.51.13"] } 其中bind_addr 是client 节点的ip地址, retry_join和start_join是server节点的ip地址。
  4. 启动server和client节点 先启动server节点 nohup consul agent -config-dir=/etc/consul.d > /data/consul/consul.log &

再分别启动三个client节点 nohup consul agent -config-dir=/etc/consul.d > /data/consul/consul.log &

2018/05/04 12:02:23 [INFO] agent: Join LAN completed. Synced with 1 initial agents 说明client节点已经加入到了consul集群。

  1. 查看各个节点的状态 consul members

consul operator raft list-peers Node ID Address State Voter RaftProtocol qabb-rdsa0 93b8e2a9-1ae1-3726-2993-c4f068ffd9b4 10.9.51.13:8300 leader true 3

  1. 通过 server节点 10.9.51.13:8500/ui 查看web ui

现在 qabb-r1db13 qabb-r1db7 上还没部署服务,所以显示为0个服务。接下来我们开始部署redis服务,构建基于Consul的Redis的高可用架构

六 基于Consul的Redis 高可用架构

Redis现有高可用架构sentinel遇到的问题

  1. Redis 哨兵架构下,服务器节点部署了哨兵,但业务部门没有在应用程序层面使用jedis哨兵驱动来自动发现Redis master,而使用直连IP master。当master挂掉,其他redis节点担当新master后,应用需要手工修改配置指向新master。
  2. Redis 客户端驱动还没有读写分离的配置,若想slave的读负载均衡,暂时没好的办法。

Consul 可以满足以上需求,配置两个DNS服务,一个是master的写服务,利用consul自身的服务健康检查和探测功能,自动发现新的master。 然后定义一个slave的读服务,基于DNS本身,能够对slave角色的redis IP做轮询,实现负载均衡的效果。

环境搭建

其实首先我们要在搭建一主两从的redis集群,因为本文是模拟练习,所以在client节点上部署。具体搭建过程省略,Redis的主从配置如下

 master 10.215.20.13:6380

 slave  10.215.20.7:6380 
        10.9.141.52:6380
定义服务配置文件

我们需要在每个client节点的/etc/consul.d/下面服务配置文件如下:

$ ll
total 12
-rw-r--r-- 1 root root 217 May  4 18:54 client.json
-rw-r--r-- 1 root root 317 May  4 18:55 r-6380-redis-test.json
-rw-r--r-- 1 root root 320 May  4 18:54 w-6380-redis-test.json

redis 主节点的服务定义配置文件 W-6380-redis-test.json

{
  "services": [
    {
      "name": "w-6380-redis-test",
      "tags": [
        "master-test-6380"
      ],
      "address": "10.215.20.13",
      "port": 6380,
      "checks": [
        {
          "args":["sh","-c","/data/consul/shell/check_redis_master.sh 6380 "],
          "interval": "15s"
        }
      ]
    }
  ]
}

redis 从节点的服务定义配置文件 r-6380-redis-test.json

{
  "services": [
    {
      "name": "r-6380-redis-test",
      "tags": [
        "slave-test-6380"
      ],
      "address": "10.215.20.7",
      "port": 6380,
      "checks": [
        {
          "args": ["sh","-c","/data/consul/shell/check_redis_slave.sh 6380 "],
          "interval": "10s"
        }
      ]
    }
  ]
}

关于服务的定义文件这里做简单说明:

Consul 默认会根据names的值定义DNS域名,默认以 .service.consul 结尾。不过我们可以利用domain参数修改。

根据上面的Redis主从服务定义配置文件,Consul client节点向server集群注册后,对应有两个域名:

w-6380-redis-test.service.consul 对应Redis master服务器ip。

r-6380-redis-test.service.consul 对应两个slave服务器ip,客户端发送请求时DNS轮训随机分配一个slave ip。

其中"args": ["sh","-c","/data/consul/shell/checkredisslave.sh 6380 "]代表对redis 6380 端口进行健康检查,如果异常返回2,consul client 会通知server端对异常服务进行服务治理。

动态加载配置

此时我们检查web-ui,

检查dns 配置

dig @10.9.51.13 -p 8600 w-6380-redis-test.service.consul

显示 10.215.20.13 对应于 w-6380-redis-test.service.consul

dig @10.9.51.13 -p 8600 r-6380-redis-test.service.consul

显示2个slave ip 10.215.20.7 ,10.9.141.52 对应 r-6380-redis-test.service.consul.

注意因为是测试,dns配置并未在我们公司的dns 域名服务器器做解析,所以日志中提示

;; WARNING: recursion requested but not available

切换演练

我们需要做2种容灾演练

  1. 读写分离,如一个slave (10.215.20.13:6380)挂了之后,观察系统的表现

继续关闭其他redis slave (10.9.141.52:6380)实例

可以看到结果符合预期: 当多个从库依次关闭,dns域名后端ip发生变化,会逐步剔除关闭的实例对应的ip,所有的slave关闭之后,域名r-6380-redis-test.service.consul 后端的ip指定到redis master对应的ip上。

  1. 配合sentinel,实现高可用,master挂了之后,观察系统的表现 在这里我选择consul集群中的server节点部署了sentinel监控,(生产中要3或者5个节点,测试过程只是部署一个)。模拟redis 主库 10.215.20.13:6380 crash。 127.0.0.1:6380> shutdown Sentinel 监控日志显示选举从库 10.215.20.7:6380 为主库。

此时我们再检查dns 域名 主库对应的dns域名 w-6380-redis-test.service.consul.对应ip已经变为10.215.20.7

r-6380-redis-test.service.consul. 对应的ip 减少了一个,变为10.9.141.52。

从目前的结果来看 切换符合预期。 另外说一下不符合预期的地方,在老的master 重新起来之后,sentinel会将老的master设置为新的slave,但是Consul 对应的dns 并未及时更新准确,需要执行consul reload 才可以。

生产过程中要注意这点,切换之后及时更新DNS缓存。

总结

从环境搭建以及测试结果来看,Consul这款工具使用起来十分简便,配合Redis sentinel 切换速度符合预期,上线生产环境时需要注意dns缓存时间的配置,以及DNS域名管理方面的支持。另外更多的技术知识点还是要多阅读Consul官方文档。

推荐阅读

  1. 本文实践参考邓亚运的文章,也推荐给大家看看http://www.cnblogs.com/gomysql/p/8010552.html
  2. Consul DNS接口相关说明 https://www.consul.io/docs/agent/dns.html
  3. 关于check用法请参考 https://www.consul.io/docs/agent/checks.html 0.92版本之后有很多改变。

原文发表时间:2018-05-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PHP实战技术

想要成为Linux大神,你应该和我一样这样做!

大神终究是孤独的,在Linux这条路上,有太多的人,而我们走着走着就分离了,我们在各自的道路上按照我们自己的方法去寻找着属于我们的道路,属于我们的那一片领土! ...

3318
来自专栏微信公众号:Java团长

JavaWeb学习总结(一)——JavaWeb开发入门

  WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源。   Internet上供外界访问的Web资源分为:

1261
来自专栏从零开始学自动化测试

appium+python自动化45-nox连不上问题解决

最新下了个最新版的夜神模拟器,然后adb devices发现连不上模拟器了,报adb server version (36) doesn’t match thi...

1051
来自专栏吴伟祥

FinderWeb2.4.9 程序员的看日志利器

http://www.finderweb.net/download/finder-web-2.4.9.war

2002
来自专栏全华班

springcloud学习手册-Config 分布式配置中心

导读 | Config分布式配置中心 ? 一、为什么需要使用配置中心来统一管理配置呢? 通常在一个分布式环境中,同类型的、不同类型的服务往往多达几个...

3884
来自专栏程序猿DD

使用Consul做服务发现的若干姿势

来源:http://blog.bossma.cn/consul/consul-service-register-and-discovery-style/?hms...

4803
来自专栏云计算教程系列

Prometheus升级指南

Prometheus是一个基于Metrics的监控系统 ,与Kubernetes同属CNCF(Cloud Native Computing Foundation...

8842
来自专栏抠抠空间

浅谈pipreqs组件(自动生成需要导入的模块信息)

2483
来自专栏24K纯开源

mac下利用Breakpad的dump文件进行调试

一、前情回顾 最近把公司的一个视频处理程序更新了一个版本,准备提交测试的发现了崩溃的情况。这个程序采用Qt和ffmpeg技术栈开发,主要用于对视频进行渲染拼接处...

5849
来自专栏前端小叙

在window的cmd窗口下运行linux命令

之前看很多视频老师都是用Linux命令操作命令框,感觉很方便,自己在cmd窗口试了一下,所有这些命令都提示不是内部或外部命令,后来发现了windows还有一个p...

3839

扫码关注云+社区