亚马逊AWS官方博客

使用 Envoy Redis Proxy 在 Amazon ElastiCache 集群进行数据同步

背景

随着 IT 信息系统在各行各业的演进越来越快,用户对 IT 信息系统的依赖性越来越强,对 IT 信息系统的可用性要求越来越高,越来越多的企业都在开展或者计划进行“同城高可用”/“异地容灾”的工作。

在对信息系统进行韧性(Resilience)/高可用(High Availability)改造的过程中,我们看到,借助于亚马逊云科技的全球基础设施,比如使用同一 Region 内的多个 AZ 进行高可用建设,使用全球多 Region 进行异地容灾的案例越来越多。

在韧性和高可用的架构设计时,我们也看到,对与数据同步到不同 AZ,不同 Region 是一个刚需,数据同步的延迟也跟随业务系统的 RTO(Recovery Time Objective)各有不同。因此,对数据库,缓存,文档数据库和对象存储针对不同的 RTO 要求设计数据同步方案是必须的。亚马逊云科技也提供了 Well-Architected Framework 来指导高可用和韧性建设。

本文中,我们将使用 Envoy 的 Redis Proxy 来构建一个双 Region,双 ElastiCache(Redis)Cluster 集群数据同步的方案。

Amazon ElastiCache 介绍

Amazon ElastiCache 是一项完全托管且兼容 Redis OSS 和 Memcached 的服务,可为现代应用程序提供实时、成本优化的性能和高达 99.99% 的可用性。ElastiCache 非常适合高性能用例,例如数据缓存、Web、移动应用程序、医疗应用程序、金融应用程序、游戏、广告技术、物联网、媒体流、会话存储、排行榜、机器学习(ML)和基于微服务的应用程序。
ElastiCache 可以提升数据库和应用程序的性能,以微秒级的响应时间扩展到每天数万亿个请求。与开源替代方案相比,优势包括增强的安全性、可靠性、可扩展性和性能。该服务还可以为读取密集型工作负载节省成本,并为内存密集型工作负载提供数据分层等成本优化功能。

Envoy

Envoy 是一个为大型现代面向服务架构设计的 L7 代理和通信总线。该项目源于“ 网络应该对应用程序透明。当网络和应用程序问题发生时,应该能够轻松确定问题的根源”这个理念。Envoy 试图通过提供以下(完整功能请参考 Envoy 官方文档)高级特性来实现这一目标:

  • Envoy 是一个独立的进程,与每个应用服务器一起运行,Envoy 可以与任何应用程序语言一起使用,透明地桥接不同的应用程序语言之间的差异;
  • Envoy 可以快速部署和升级,在整个基础设施中实现一致的可观察性、安全性和流量控制;
  • Envoy 是一个 L3/L4 网络代理,可插拔的过滤器链机制允许编写过滤器来执行不同的 TCP/UDP 代理任务,并将其插入到主服务器中,支持以下过滤器:
    • 原始 TCP 代理
    • UDP 代理
    • HTTP 代理
    • TLS 客户端证书认证
    • Redis 代理
    • MongoDB 代理
    • Postgres 代理
  • Envoy 支持额外的 HTTP L7 过滤器层。HTTP 过滤器可以插入到 HTTP 连接管理子系统中,执行不同的任务,例如:
    • 缓冲
    • 速率限制
    • 路由/转发
    • 探测 Amazon DynamoDB

本文中,我们主要使用 Redis 代理来达到多 Region 双 ElastiCache 集群数据同步的功能。

前置条件

  • 两个 ElastiCache 集群(2.6 和 v6.0.5),本文一个集群位于香港 Region,另外一个位于新加坡 Region
  • 一个用以模拟 Redis Proxy 的 EC2 主机(Amazon Linux2023)

本文中我们使用亚马逊云科技新加坡区域和香港区域 – 其中新加坡区域为主区域,香港区域为容灾区域。整体的拓扑结构如下:

Redis Proxy 部署

Redis Proxy 可以单独作为一个组件部署在 EC2 主机,也可以和应用的 Kuberntes Pod 以边车(Sidecar)的形式部署在容器内,本文将 Redis Proxy 以 docker 容器的形式部署在 EC2 主机上。

基础镜像:envoyproxy/envoy:v1.17.0

准备 Dockerfile

FROM envoyproxy/envoy:v1.17.0
COPY ./envoy.yaml /etc/envoy/envoy.yaml
RUN chmod go+r /etc/envoy/envoy.yaml

其中 envoy.yaml 文件为配置 ElastiCache 的关键配置文件,具体内容如下:

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
      protocol: TCP
      address: 0.0.0.0
      port_value: 1936
static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 9091
    filter_chains:
    - filters:
      - name: envoy.filters.network.redis_proxy
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.redis_proxy.v3.RedisProxy
          stat_prefix: redis_proxy
          settings:
            op_timeout: 1s
            enable_redirection: true
          prefix_routes:
            catch_all_route:
              cluster: singapore_redis
              request_mirror_policy:
                cluster: hongkong_cluster
                exclude_read_commands: true
  clusters:
  - name: singapore_redis
    connect_timeout: 3s
    cluster_type:
      name: envoy.clusters.redis
    dns_lookup_family: V4_ONLY
    load_assignment:
      cluster_name: singapore_redis
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: singapore-redis.xyzhelloredis.clustercfg.apse1.cache.amazonaws.com
                port_value: 6379
  - name: hongkong_cluster
    connect_timeout: 3s
    cluster_type:
      name: envoy.clusters.redis
    dns_lookup_family: V4_ONLY
    load_assignment:
      cluster_name: hongkong_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: hongkong-redis.xyzhelloredis.clustercfg.ape1.cache.amazonaws.com
                port_value: 6379

其中将 redis 流量复制到灾备集群的关键配置如下:

  • enable_redirection:当遇到 MOVED 和 redirection 的错误时进行重试
  • request_mirror_policy:流量镜像配置
  • cluster:流量镜像的目标集群
  • exclude_read_commands:是否将读命令也流量镜像到灾备集群。

构建 docker 镜像(docker built -t kadanli/redis-envoy:v0.1 .)并运行:

docker run -p 1936:1936 -p 9091:9091 kadanli/redis-envoy:v0.1

查看容器运行情况:

连接 Redis Proxy 容器进行测试:

查看主集群和灾备集群的数据情况:

总结

借助 Envoy 的 Redis Proxy,我们可以高效稳定地将 Redis 的流量有选择地复制到灾备集群(譬如排除读操作,仅复制增,改和删除操作)。对比类似 RIOT 等同步工具,Envoy 需要对应用侧的连接方式进行改造,从直接连接 Redis 集群变更为连接 Redis Proxy。因此在数据复制方案的选择上我们应当有所权衡。

参考链接

Envoy:

ElastiCache:https://docs.aws.amazon.com/elasticache/

RIOT:https://redis.io/docs/latest/integrate/riot/

AWS Well Architecture:https://docs.aws.amazon.com/wellarchitected/latest/framework/welcome.html

本篇作者

李俊杰

亚马逊云解决方案架构师,负责云计算方案的咨询与架构设计,同时致力于容器方面研究和推广。在加入亚马逊云科技之前曾在金融行业 IT 部门负责传统金融系统的现代化改造,对传统应用的改造,容器化具有丰富经验。