亚马逊AWS官方博客
百尺竿头更进一步 – 拓展 Aurora的读写能力之Gaea篇
1.前言
Amazon Aurora 是亚马逊云科技自研的一项关系数据库服务,它在提供和开源数据库MySQL、PostgreSQL的完好兼容性同时,也能够提供和商业数据库媲美的性能和可用性。性能方面,Aurora MySQL能够支持到与开源标准MySQL同等配置下五倍的吞吐量,Aurora PostgreSQL能够支持与开源标准PostgreSQL同等配置下三倍的吞吐量的提升。在扩展性的角度,Aurora在存储与计算、横向与纵向方面都进行了功能的增强和创新。
Aurora的最大数据存储量现在支持多达128TB,而且可以支持存储的动态收缩。计算方面,Aurora提供多个读副本的可扩展性配置支持一个区域内15个多达15个读副本的扩展,提供多主的架构来支持同一个区域内4个写节点的扩展,提供Serverless无服务器化的架构实例级别的秒级纵向扩展,提供全球数据库来实现数据库的低延迟跨区域扩展。
随着用户数据量的增长,Aurora已经提供了很好的扩展性,那是否可以进一步增强更多的数据量、更多的并发访问能力呢?您可以考虑利用分库分表的方式,来支持底层多个Aurora集群的配置。基于此,包含这篇博客在内的系列博客会进行相应的介绍,旨在为您进行分库分表时代理选择提供参考。
本篇博客会聚焦如何使用开源的Gaea proxy ,一个开源的分库分表中间件工具,来进行数据库集群的构建。会涵盖分库分表、读写分离、分片表关联查询和failover自动识别等方面。
2.Gaea介绍
Gaea是某互联网电商开源的基于mysql协议的数据库中间件,Gaea支持分库分表、sql路由、读写分离,配置热加载,连接池,自定义SQL拦截与过滤等基本特性,并支持分片表和全局表的join、支持多个分片表但是路由规则相同的join。
更多功能介绍,请参阅Github 最新说明
2.1 设计架构图
gaea包含四个模块,分别是gaea-proxy、gaea-cc、gaea-agent、gaea-web。gaea-proxy为在线代理,负责承接sql流量,gaea-cc是中控模块,负责gaea-proxy的配置管理及一些后台任务,gaea-agent部署在mysql所在的机器上,负责实例创建、管理、回收等工作,gaea-web是gaea的一个管理界面,使gaea整体使用更加方便。
2.2 基本概念
- cluster
集群, 按照业务重要程度划分集群, 一个集群内可包含多个gaea-proxy实例, 通过指定gaea-proxy启动时依赖的配置文件中的cluster_name 确定该proxy所属集群。集群内的proxy实例只为该集群内的namespace提供服务, 起到物理隔离的作用。 一套集群可为多个namespace提供服务。
- namespace
命名空间,每一个业务系统对应一个namespace,一个namespace对应多个database,业务方可以自由切换。 每个namespace理论上只会属于一个集群。 通过gaea-cc配置管理接口, 指定namespace所属集群。
- slice
分片,逻辑上的分组,一个分片包含mysql一主多从。
- shard
分表规则,确定一个表如何分表,包括分表的类型、分布的分片位置。
- proxy
指代理本身,承接线上流量。
- gaea_cc
代理控制模块,主要负责配置下发、实例监控等。
2.3 部署架构图
在生产环境中可以参考以下部署架构图来实现多mysql 集群的代理和集中式的配置管理,图中gaea核心集群和普通集群没有区别。
说明:部署架构图中的gaea-cc 和etcd 在生产环境中充当配置下发和配置持久化的角色。在测试环境中可以用json 文件静态配置做演示,以下测试为基于json 文件做的测试。
3.环境构建
在以下的测试环境中,我们使用一台EC2 安装Gaea,并使用json 文件静态配置来验证功能,后端Aurora 创建3套集群来做3分片。
3.1 Aurora 集群
首先创建三套Aurora MySQL集群,机型为db.r5.2xlarge,每套集群有一个写节点一个读节点。
3.2 Gaea proxy 搭建
1)安装Go 语言环境
2)下载源码并编译
git clone https://github.com/XiaoMi/Gaea.git
cd Gaea && make
完成后会在bin 目录出现gaea and gaea-cc
[ec2-user@ip-172-31-29-68 bin]$ ls
gaea gaea-cc
3.3 Proxy 配置
gaea配置由两部分组成,本地配置为gaea_proxy直接使用的配置内容,一般不需要在运行时改变。gaea为多租户模式,每个租户称为一个namespace,namespace 的配置在运行时都可变,一般存放在etcd中,以下以json 文件替代etcd 做演示,配置的详细说明请参考Github 的说明。
1)准备好本地基础配置文件,该文件用于gaea 的全局配置,该配置文件放在$Gaea_Home/etc,参考以下例子:
2) 准备好sharding 的配置文件
gaea 支持多租户,每个租户单独一个namespace,每个namespace 一个配置文件
gaea 支持kingshard 和mycat 两种sharding 方式,本次测试使用kingshard 的hash方式分表,
namespace 配置文件必须位于gaea 编译目录 etc/file/namespace 目录下,以下配置主要做这些事项:
- 同时开启kingshard 和mycat 两种分库分表方式(测试只用kingshard 这种)
- 配置前端接受请求的用户(gaea)和后端连接Aurora 的用户(root)
- 启用读写分离
- 数据分片规则如下:
- 使用kingshard 的hash 方式对tbl_ks 做了3个物理集群(slice),分片key 配置的是id 字段
- 3个物理分片下都有一个分表(location 1,1,1)
- 把tbl_ks2表配置成tbl_ks 的关联表(proxy自动会根据父表的分片规则把子表数据分布到同slice中以方便做join和关联查询)
- 把tbl_global 配置成全局表(所有分片都有这个表的全量数据)
- 非分片查询的SQL 默认发送到slice 1(default_slice”: “slice-1)
3.4 启动Proxy
使用bin 目录下的gaea 二进制文件启动,指定好静态配置文件路径
3.5 验证连接
使用动态配置文件中指定的用户名和密码连接proxy,因为上面的动态配置文件开启了kingshard 和mycat 两种分库分表方式,所以登陆后默认看到两个预先配置好的proxy里的database:
4.功能测试
4.1 分库分表验证
Gaea 因为对DDL兼容性一般,官网建议预先在后端数据库创建好对应的数据库然后再在proxy应用规则。因为我们使用kingshard 的hash 规则分表,我们预先在每个Aurora 建好相应的数据库和表,注意:table 必须是从0000 开始
Slices | DataBase | endpoint | table |
slice 0 | db_ks | shard-1.cluster-c3luzotrlr7v.ap-southeast-1.rds.amazonaws.com | tbl_ks_0000 |
slice 1 | db_ks | shard-2.cluster-c3luzotrlr7v.ap-southeast-1.rds.amazonaws.com | tbl_ks_0001 |
slice 2 | db_ks | shard-3.cluster-c3luzotrlr7v.ap-southeast-1.rds.amazonaws.com | tbl_ks_0002 |
- 插入数据并查看
- 分别登陆3个aurora 检查数据,验证按id 做了hash 分布
4.2 全局表测试
全局表是在各个slice上 (准确的说是各个slice的各个DB上) 数据完全一致的表,方便执行一些跨分片查询,如果是小表和分片表做join推荐使用全局表这种方式,对应在shard_rules 的配置如下这段:
测试过程如下:
- 在Aurora 后端数据库建表
同样的,因为Gaea 不支持DDL,需要先在所有后端数据库建好表,再应用规则
- 连接proxy并 插入数据
插入一行会提示3 rows affected
- 登陆每一个aurora 看是否插入了3行数据
- 做全局表和分片表join的测试
- 通过执行计划来验证
4.3 全局表数据一致性测试
先说结论,通过proxy写全局表的时候,这个事务不是原子性的。
假如分片1的全局表存在了id=1,其他两个分片没有这条数据,这时候从proxy insert id=1会报错但是分片2 和3 都可以成功写入本地, 所以需要定期检查全局表是否数据一致。
4.4 父表和子表做join 查询
1) 验证子表的数据分布
从上面的执行结果确认子表也是按照父表的规则做了分片,并且id 字段hash后和父表在同分片
2)验证父表和子表做join 查询
# join 测试
从上面执行结果看,父表和子表可以通过sharding key 做关联做join 查询。
4.5 检查读写分离是否实现
编写脚本验证读请求是否都发往从库执行
结果如下图所示,所有的读请求都发往了replica 节点执行,主节点没有收到查询请求
4.6. 故障恢复验证
此测试在于验证当Aurora failover 的时候验证proxy 是否能在不改变配置的情况下自动识别failover 的发生并自动恢复。
测试脚本如下:
运行脚本,然后在Aurora集群的写节点上点击Action→Failover。会启动Aurora写节点和读节点的自动切换。在切换过程中,整个集群的读/写endpoint和只读endpoint维持不变,只是底层映射的节点发生变化。
从Event 看 aurora 30秒内完成failover
但是从脚本输出看,proxy 一直在报错,不能自动发现failover 事件
需要重启proxy 才能恢复正常的写入
5.结语
本篇文章通过数据库中间件的方法来拓展了Aurora的分库分表能力和读写分离的能力。通过Gaea,这个方案能够实现连接池、SQL的兼容性、跨分片路由、读写分离、分片表和全局表join以及父表和子表做关联查询的能力。不足之处在于Gaea 在aurora failover 发生后不能识别和自动恢复,需要重启或者手动刷新配置等方式才能恢复。
后续我们会继续推出对其他中间件的拓展和研究系列博客。
相关博客
百尺竿头更进一步-Aurora读写能力扩展之Sharding-JDBC篇
百尺竿头更进一步 – Amazon Aurora的读写能力扩展之ShardingSphere-Proxy篇