基于consul的Redis高可用方案

标签: | 发表时间:2018-05-07 22:22 | 作者:
出处:https://mp.weixin.qq.com

一 前言

这几天在研究如何做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集群。

  5. 查看各个节点的状态 

    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
  6. 通过 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/check redisslave.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上。

  2. 配合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版本之后有很多改变。


相关 [consul redis] 推荐:

基于consul的Redis高可用方案

- -
这几天在研究如何做Redis的高可用容灾方案,查询了资料和咨询DBA同行,了解到Redis可以基于consul和sentinel实现读写分离以及HA高可用方案. 本文讲述基于consul的Redis高可用方案实践. 感谢邓亚运的提示和资料协助. Consul是HashiCorp公司基于go语言研发用于服务发现和配置共享开的分布式高可用的系统.

安装Consul集群

- - 周立的博客 - 关注Spring Cloud、Docker
本文基于Consul 1.5.3,理论适用于Consul 1.6及更低版本. 运行一个consul agent. 将agent加入到consul集群. 列出consul cluster集群中的members. 这里只列出几个常用的命令,consul有将近20个命令,本文不作展开,详见: https://www.consul.io/docs/commands/index.html.

[转]consul VS zookeeper、etcd、doozerd

- - Xiao_Qiang_的专栏
  zookeeper、doozerd、etcd都有着相似的架构,这三者的服务节点都需要一个仲裁节点来操作,它们是强一致的,并提供各种操作原语. 应用程序可以通过客户端lib库来构建分布式的系统. 在一个单datacenter中,consul的server节点工作在一种简单的方式下,consul server需要一个仲裁操作,并提供强一致性.

Consul 常用url链接

- - Share

服务发现:Zookeeper vs etcd vs Consul

- - 企业架构 - ITeye博客
服务发现:Zookeeper vs etcd vs Consul. 【编者的话】本文对比了Zookeeper、etcd和Consul三种服务发现工具,探讨了最佳的服务发现解决方案,仅供参考. 如果使用预定义的端口,服务越多,发生冲突的可能性越大,毕竟,不可能有两个服务监听同一个端口. 管理一个拥挤的比方说被几百个服务所使用的所有端口的列表,本身就是一个挑战,添加到该列表后,这些服务需要的数据库和数量会日益增多.

基于 Consul 的 Docker Swarm 服务发现

- - IT瘾-dev
基于 Consul 的 Docker Swarm 服务发现. 2017 年 1 月 10 日发布. Docker 是一种新型的虚拟化技术,它的目标在于实现轻量级操作系统的虚拟化. 相比传统的虚拟化方案,Docker. 虚拟化技术有一些很明显的优势:启动容器的速度明显快于传统虚拟化技术,同时创建一台虚拟机占用的资源也要远远小于传统的虚拟技术.

Consul注销实例时候的问题

- - 程序猿DD
当我们在Spring Cloud应用中使用Consul来实现服务治理时,由于Consul不会自动将不可用的服务实例注销掉(deregister),这使得在实际使用过程中,可能因为一些操作失误、环境变更等原因让Consul中存在一些无效实例信息,而这些实例在Consul中会长期存在,并处于断开状态. 它们虽然不会影响到正常的服务消费过程,但是它们会干扰我们的监控,所以我们可以实现一个清理接口,在确认故障实例可以清理的时候进行调用来将这些无效信息清理掉.

基于Consul的数据库高可用架构 - yayun - 博客园

- -
      几个月没有更新博客了,已经长草了,特意来除草. 本次主要分享如何利用consul来实现redis以及mysql的高可用. 以前的公司mysql是单机单实例,高可用MHA加vip就能搞定,新公司mysql是单机多实例,那么显然这个方案不适用,后来也实现了故障切换调用dns api来修改域名记录,但是还是没有利用consul来实现高可用方便,后面会说明优势.

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

- - 程序猿DD
从2016年起就开始接触Consul,使用的主要目的就是做服务发现,后来逐步应用于生产环境,并总结了少许使用经验. 最开始使用Consul的人不多,为了方便交流创建了一个QQ群(群号在最后),这两年微服务越来越火,使用Consul的人也越来越多,目前群里已有400多人,经常有人问一些问题,比如:. 服务注册到节点后,其他节点为什么没有同步.

注册中心 Consul 使用详解 - 纯洁的微笑博客

- -
在上个月我们知道 Eureka 2.X 遇到困难停止开发了,但其实对国内的用户影响甚小,一方面国内大都使用的是 Eureka 1.X 系列,另一方面 Spring Cloud 支持很多服务发现的软件,Eureka 只是其中之一,下面是 Spring Cloud 支持的服务发现软件以及特性对比:. (弱)长连接,keepalive.