如何正确处理异步数据库复制?

Ben*_*min 7 scalability database-replication amazon-rds

我正在考虑使用带有只读副本的Amazon RDS来扩展我们的数据库.

我们的Web应用程序中的一些控制器是可读/写的,其中一些是只读的.我们已经有了一种自动识别哪些控制器是只读的方法,因此我的第一种方法是在请求读/写控制器时打开与主站的连接,否则在请求读取时打开与读取副本的连接.只有控制器.

从理论上讲,这听起来不错.但后来我偶然发现了复制延迟概念,它基本上说复制品可以在主机后面几秒钟.

让我们想象下面的用例:

  • 浏览器发布到/create-account,即读/写,从而连接到主服务器
  • 创建帐户,提交事务,并将浏览器重定向到 /member-area
  • 浏览器打开/member-area,这是只读的,因此连接到副本.如果副本甚至稍微落后于主副本,则副本上的用户帐户可能尚不存在,从而导致错误.

您如何在应用程序中实际使用只读副本,以避免这些潜在问题?

sbr*_*ges 1

这是一个难题,并且有很多潜在的解决方案。一个可能的解决方案是看看facebook 做了什么,

TLDR - 读取请求被路由到只读副本,但如果您执行写入操作,那么在接下来的 20 秒内,所有读取都会发送到可写主副本。

我们必须解决的另一个主要问题是,只有我们位于加利福尼亚州的主数据库可以接受写入操作。这一事实意味着我们需要避免提供从弗吉尼亚州进行数据库写入的页面,因为每个页面都必须跨越全国到达加利福尼亚州的主数据库。幸运的是,我们最常访问的页面(主页、个人资料、照片页面)在正常操作下不会执行任何写入操作。因此,问题归结为,当用户发出页面请求时,我们如何决定将其发送到弗吉尼亚州是“安全”还是必须路由到加利福尼亚州?

这个问题有一个相对简单的答案。用户向 Facebook 发出的请求首先命中的服务器之一称为负载均衡器;这台机器的主要职责是选择一个 Web 服务器来处理请求,但它也有许多其他目的:防止拒绝服务攻击和多路复用用户连接等等。该负载均衡器能够在第 7 层模式下运行,它可以检查用户请求的 URI,并根据该信息做出路由决策。此功能意味着可以轻松地告诉负载均衡器我们的“安全”页面,并且它可以根据页面名称和用户位置决定是否将请求发送到弗吉尼亚州或加利福尼亚州。

然而,这个问题还有另一个问题。假设您去 editprofile.php 更改您的家乡。此页面未标记为安全,因此它会路由到加利福尼亚州,然后您进行更改。然后您去查看您的个人资料,由于这是一个安全页面,我们会将您发送到弗吉尼亚州。然而,由于我们之前提到的复制滞后,您可能看不到刚刚所做的更改!这种体验对于用户来说非常令人困惑,并且还会导致重复发布。每当您向我们的数据库写入内容时,我们都会在您的浏览器中设置一个包含当前时间的 cookie,从而解决了这个问题。负载均衡器也会查找该 cookie,如果它注意到您在 20 秒内写了一些内容,就会无条件地将您发送到加利福尼亚州。然后,当 20 秒过去并且我们确定数据已复制到弗吉尼亚时,我们将允许您返回安全页面。