Skip to main content

5.使用复制进行横向扩展

可以使用复制作为横向扩展解决方案; 也就是说,可以在一些合理的限制内将数据库查询的负载分散到多个数据库服务器上。

由于复制是从一个源分布到一个或多个副本进行的,因此在具有大量读取和少量写入/更新的环境中,使用复制进行横向扩展效果最佳。 大多数网站都属于这一类别,用户正在浏览网站、阅读文章、帖子或查看产品。 更新仅在会话管理期间、或进行购买或向论坛添加评论/消息时发生。

在这种情况下,复制能够将读取分布到副本上,同时仍然使 Web 服务器能够在需要写入时与源进行通信。 可以在图 19.1 “使用复制来提高横向扩展期间的性能”中看到此场景的示例复制布局。

图 19.1 在横向扩展期间使用复制来提高性能

1708867897824

如果负责数据库访问的代码部分已被正确抽象/模块化,那么将其转换为使用复制设置运行应该非常顺利和容易。 更改数据库访问的实现以将所有写入发送到源,并将读取发送到源或副本。 如果您的代码不具有这种抽象级别,那么设置复制系统可以提供清理它的机会和动力。 首先创建一个实现以下功能的包装器库或模块:

  • safe_writer_connect()
  • safe_reader_connect()
  • safe_reader_statement()
  • safe_writer_statement()

每个函数名称中的 safe_ 表示该函数负责处理所有错误情况。 可以为函数使用不同的名称。 重要的是要有一个统一的接口来连接读取、连接写入、执行读取和执行写入。

然后转换客户端代码以使用包装器库。 一开始这可能是一个痛苦和可怕的过程,但从长远来看它是有回报的。 使用刚刚描述的方法的所有应用程序都能够利用源/副本配置,甚至涉及多个副本的配置。 代码更容易维护,并且添加故障排除选项也很简单。 只需要修改一两个函数(例如,记录每个语句花费的时间,或者发出的语句中的哪个语句给带来了错误)。

如果编写了很多代码,可能希望通过编写转换脚本来自动执行转换任务。 理想情况下,代码使用一致的编程风格约定。 如果没有,那么最好还是重写它,或者至少仔细检查并手动规范它以使用一致的样式。