PostgreSQL 和特定于连接的写入一致性设置

文章的翻译是专门为课程的学生准备的 “数据库”。 有兴趣往这个方向发展吗? 我们邀请您参加 开放日,我们详细讨论了该计划、在线格式的特点、培训后等待毕业生的能力和职业前景。

PostgreSQL 和特定于连接的写入一致性设置

PostgreSQL 和特定于连接的写入一致性设置
在 Compose,我们处理许多数据库,这使我们有机会更加熟悉它们的功能和缺点。 当我们逐渐喜欢新数据库的功能时,我们有时会开始思考,如果我们长期使用的更成熟的工具中也存在类似的功能,那该多好。 我希望在 PostgreSQL 中看到的新功能之一是整个集群中每个连接的可配置写入一致性。 事实证明,我们已经拥有它,今天我们想与您分享有关如何使用它的信息。

我为什么需要这个?

集群的行为方式取决于您的应用程序。 以账单支付应用程序为例。 您将需要整个集群 XNUMX% 的一致性,因此您必须启用同步提交,以便数据库等待所有更改的完成。 但是,如果您的应用程序是一个快速增长的社交网络,那么您可能更喜欢快速响应而不是 XNUMX% 一致性。 为此,您可以在集群中使用异步提交。

满足妥协

您必须在数据一致性和性能之间进行权衡。 PostgreSQL 放弃了一致性,因为默认配置是可预测的并且不会出现意外的情况。 现在让我们看看妥协的情况。

权衡 1:性能

如果PostgreSQL集群不需要一致性,可以异步运行。 写入是对集群领导者进行的,更新将在几毫秒后发送到其副本。 当PostgreSQL集群需要一致性时,它必须同步运行。 写入将发送到集群领导者,集群领导者将向副本发送更新,并等待每个副本都已写入的确认,然后向发起写入成功的客户端发送确认。 这些方法之间的实际区别在于,异步方法需要两个网络跃点,而同步方法需要四个网络跃点。

权衡 2:一致性

这两种方法如果领导者失败,结果也会不同。 如果工作是异步执行的,那么如果发生此类错误,副本将不会提交所有记录。 会损失多少? 取决于应用程序本身和复制的效率。 如果副本中的信息量比领导者少 1 MB,Compose 复制将阻止副本成为领导者,也就是说,在异步操作期间可能会丢失多达 1 MB 的记录。

在同步模式下不会发生这种情况。 如果领导者发生故障,所有副本都会更新,因为领导者上确认的任何写入都必须在副本上确认。 这就是一致性。

同步行为在计费应用程序中很有意义,其中一致性在一致性和性能之间的权衡中具有明显的优势。 对于此类应用程序来说,最重要的是有效数据。 现在考虑一个社交网络,其中的主要任务是通过尽快响应请求来保持用户的注意力。 在这种情况下,具有更少网络跃点和更少等待提交的性能将是优先考虑的。 然而,性能和一致性之间的权衡并不是您必须考虑的唯一问题。

权衡 3:崩溃

了解集群在故障期间的行为非常重要。 考虑一个或多个副本发生故障的情况。 当异步处理提交时,领导者将继续运行,即接受并处理写入,而无需等待丢失的副本。 当副本返回集群时,它们会赶上领导者。 使用同步复制,如果副本没有响应,那么领导者将别无选择,将继续等待提交确认,直到副本返回集群并可以接受并提交写入。

每笔交易一个连接?

每个应用程序都需要不同类型的一致性和性能组合。 当然,除非它是我们想象中完全一致的账单支付应用程序,或者是我们几乎短暂的社交网络应用程序。 在所有其他情况下,有时某些操作必须同步,而某些操作必须异步。 您可能不希望系统等到发送到聊天的消息被提交,但如果在同一应用程序中处理付款,那么您将不得不等待。

当然,所有这些决定都是由应用程序开发人员做出的。 就何时使用每种方法做出正确的决定将有助于您充分利用集群。 开发人员可以在 SQL 级别在连接和事务之间进行切换,这一点很重要。

确保实践中的控制

默认情况下,PostgreSQL 提供一致性。 这是由服务器参数控制的 synchronous_commit。 默认情况下它处于位置 on,但它还有其他三个选项: local, remote_write или off.

当将参数设置为 off 所有同步提交都会停止,即使在本地系统上也是如此。 local 参数指定本地系统的同步模式,但对副本的写入是异步执行的。 Remote_write 更进一步:对副本的写入是异步进行的,但当副本已接受写入但尚未将其写入磁盘时返回。

通过考虑可用的选项范围,我们选择一种行为,并记住 on – 这些是同步录音,我们将选择 local 用于通过网络进行异步提交,同时保持本地提交同步。

现在,我们稍后将告诉您如何进行设置,但想象一下我们设置 synchronous_commit в local 对于服务器。 我们想知道是否可以更改参数 synchronous_commit 事实证明,这不仅是可能的,甚至还有两种方法可以做到这一点。 首先是设置连接的会话,如下所示:

SET SESSION synchronous_commit TO ON;  
// Your writes go here

会话中的所有后续写入将在向连接的客户端返回肯定结果之前确认对副本的写入。 当然除非你改变设置 synchronous_commit 再次。 可以省略部分 SESSION 在命令中,因为它将采用默认值。

当您只想确保获得单个事务的同步复制时,第二种方法很好。 在许多 NoSQL 生成数据库中不存在事务的概念,但在 PostgreSQL 中存在。 在这种情况下,您启动一​​个事务,然后设置 synchronous_commit в on 在执行交易条目之前。 COMMIT 将使用任何参数值提交事务 synchronous_commit,这是当时设置的,尽管最好预先设置该变量以确保其他开发人员了解写入不是异步的。

BEGIN;  
SET LOCAL synchronous_commit TO ON;  
// Your writes go here
COMMIT;  

现在,在数据库向连接的客户端返回肯定响应之前,所有事务提交都将被确认为写入副本。

设置 PostgreSQL

在此之前,我们设想了一个 PostgreSQL 系统 synchronous_commit,安装在 local。 为了在服务器端实现这一点,您需要设置两个服务器配置选项。 多一个参数 synchronous_standby_namessynchronous_commit 将在 on。 它决定哪些副本有资格进行同步提交,我们将其设置为 *,这意味着所有副本都参与其中。 这些值通常配置在 配置文件 通过增加:

synchronous_commit = local  
synchronous_standby_names='*'

通过设置参数 synchronous_commit 转化为意义 local,我们创建一个系统,其中本地磁盘保持同步,但网络副本提交默认情况下是异步的。 当然,除非我们决定使这些提交同步,如上所示。

如果您一直关注事态发展 调速器项目,您可能已经注意到最近的一些变化(1, 2),这允许调速器用户测试这些参数并监控它们的一致性。

再说几句话...

就在一周前,我可能会告诉你,不可能对 PostgreSQL 进行如此精细的调整。 就在那时,Compose 平台团队的成员 Kurt 坚称存在这样的机会。 他平息了我的反对意见,并在 PostgreSQL 文档中找到了 以下:

PostgreSQL 和特定于连接的写入一致性设置

此设置可以随时更改。 任何事务的行为均由提交时有效的设置决定。 因此,某些事务同步提交而另一些事务异步提交是可能且有用的。 例如,强制一个 multistatement 当参数默认值相反时,事务要异步提交,设置 SET LOCAL synchronous_commit TO OFF 在一笔交易中。

通过对配置文件的这个小修改,我们让用户可以控制其一致性和性能。

来源: habr.com

添加评论