我最近设置了一个只读副本,以减轻我的 Amazon 多可用区 RDS 实例的一些读取负载。亚马逊文档明确指出,“由您的应用程序决定读取流量如何在您的只读副本中分布”。
有没有人想出一种可管理的方式来扩展只读副本?将我的应用程序的不同部分硬编码以从特定副本读取,这似乎不是一个非常可扩展的解决方案。有没有一种类似于将 EC2 实例放在负载均衡器后面的方法来设置它?
我最近设置了一个只读副本,以减轻我的 Amazon 多可用区 RDS 实例的一些读取负载。亚马逊文档明确指出,“由您的应用程序决定读取流量如何在您的只读副本中分布”。
有没有人想出一种可管理的方式来扩展只读副本?将我的应用程序的不同部分硬编码以从特定副本读取,这似乎不是一个非常可扩展的解决方案。有没有一种类似于将 EC2 实例放在负载均衡器后面的方法来设置它?
AWS 工程师在此处对这个问题提供了一些见解。
以下是他的回应片段:
一般来说,您可以在以下 3 个逻辑位置对流量进行负载平衡:
- 应用层 - 创建多个连接池并将所有读取发送到只读副本。
- Web 框架/中间件 - 一些 Web 框架具有对多个数据库的内置支持 [1]。
- 外部代理 - 您可以使用外部代理,如 MySQLproxy [2]。
[1] - https://docs.djangoproject.com/en/dev/topics/db/multi-db/
我认为HAProxy将是在多个只读副本之间进行负载平衡的不错选择。你可以有这样的配置:
listen mysql-cluster 0.0.0.0:3306
mode tcp
balance roundrobin
option mysql-check user root
server db01 x.x.x.x:3306 check
server db02 x.x.x.x:3306 check
server db03 x.x.x.x:3306 check
其中 xxxx 是副本端点。
我一直在搞乱使用 Route 53 加权 CNAME 来负载平衡 RDS 只读副本(和源)。我目前有 readdb.example.com 的 3 个 CNAME 记录集。
第一个指向 db.example.com 上的源数据库。这是为了防止出现复制错误。应用程序可以回退到原始数据库进行读取。或者,如果您愿意,您可以让源承担一定比例的读取负载,具体取决于您设置权重的方式。路由策略设置为加权。我将源的权重设置为 1,因此读取负载的负担非常小。TTL 设置为低。我尝试了从 1 到 10 的值。我现在将其保留为 10。您还必须输入任何唯一字符串(“源数据库”)的集合 ID。
第二个记录集指向其中一个只读副本 (readdb1.blahblah.rds.amazonaws.com)。路由策略是加权的,TTL 和以前一样是 10。它还需要一个唯一的 Set ID。我将这个重量设置在 5-50 之间,具体取决于。这个,我确实与健康检查相关联,你必须提前创建。您可能可以使用指向副本的简单运行状况检查,但我做了一些不同的事情。
我在我的每个应用程序服务器上都放了一个这样的文件(我使用的是 PHP Elastic Beanstalk,但你可以在我假设的其他设置/语言中做类似的事情):
<?php if($instanceid = $_GET["id"]): ?>
<?php
exec("aws rds describe-db-instances --db-instance-identifier " . escapeshellarg($instanceid), $rdsinfo);
$rdsinfo = implode(' ',$rdsinfo);
$rdsinfo = json_decode($rdsinfo, true);
if($rdsinfo["DBInstances"][0]["StatusInfos"][0]["Normal"] && $rdsinfo["DBInstances"][0]["DBInstanceStatus"] === "available"){
echo "GOOD!";
}
else {
echo "BAD!";
};
/* Then there's some other stuff in here that is a little unrelated to the question */
?>
<?php endif ?>
此文件使用安装在 Elastic Beanstalk 应用程序上的 AWS 命令行界面,并且只需要提前指定 AWS_ACCESS_KEY_ID、AWS_DEFAULT_REGION 和 AWS_SECRET_KEY 的环境变量。然后,您进行指向http://www.example.com/rdshealthcheck/rdsshealthcheck.php?id=readdb1的 Route 53 健康检查。您将搜索字符串设置为“GOOD!” 我认为搜索字符串的费用为 1 美元/月/健康检查,这似乎是合理的。
如果您有第二个只读副本,您可以创建另一个指向http://www.example.com/rdshealthcheck/rdsshealthcheck.php?id=readdb2或其他名称的运行状况检查。
我实际上此时只使用了一个只读副本,但它比我的源数据库大得多。这对我来说更经济,因为我的源数据库是多可用的。我保留第三个记录集和第二个健康检查,以防第一个副本给我带来问题。这样,我不必等待第一个删除再重新启动它。相反,我立即删除第一个并使用第三个记录集中指定的名称(和第二个健康检查)启动第二个。
我想建议更方便的方法。
即,使用Amazon Route 53进行DNS 循环。
正如您在本文中看到的,
Amazon Route 53可以使用多个 CNAME 进行循环。
那么你需要做的就是
就我而言,这种方法效果很好。