很多技巧是找到您的确切要求,而您的要求听起来仍然很模糊。你只需要支持这样的操作吗?
你提到你需要最终的一致性。因此,如果您进行一次更新,它最终会复制到任何地方。如果您进行两次几乎同时的更新,您会在乎哪一次获胜吗?如果一个副本报告更新已成功完成,您是否关心如果该副本在不久之后临时崩溃,是否会丢失该值?或者如果该复制品被永久销毁?
最近应该有多精确?如果有 netsplit 之类的,查找可能会返回一个非常陈旧的结果或者只是失败。你在乎哪个?
您是否需要支持更高级的操作,例如...
- 获取密钥 K 的绝对最新值?
- 如果最新的值当前是 V,则将键 K 的值更新为值 V'?
您是否有严格的可靠性、延迟和/或带宽要求?您的副本相距多远/之间的网络有多好?这会影响您是否可以在每次更新甚至每次查找时进行跨副本通信;或者即使您可以/应该将操作故障转移到远程副本,如果本地副本似乎已关闭。
根据您在此处的回答,我使用了几种可能满足您要求的不同方案。它们有几种可能的变化。
- 最简单的事情是让应用程序始终与本地副本通信。副本时间戳值(使用 NTP 同步时钟)并且仅在异步复制时相互通信。最高时间戳在复制中获胜。当然,如果两个不同副本上的应用程序每个都几乎同时进行读/修改/写,则其中一个修改很容易丢失。(事实上,如果没有条件更新方案,对于同一个副本上几乎同时发生的更改也是如此。)如果一个副本永久失败,最近的更新可能会丢失。这或多或少是 Bigtable 的内置复制所做的。在您链接的论文中,它是“Optimistic - Multimaster”分支,但不太关心丢失一些更新,这比他们建议的要简单。
- 一些数据库使用 Paxos 算法(例如,请参见此处的“Internet-Scale Single-Sign-On 的数据管理”让更美妙的事情成为可能。每个副本都可以知道它可能落后多远,因此您可以说“给我一个不超过 1 分钟的值”或“给我绝对最新的值”。在一定数量的副本接受之前,更新不会被视为完成,因此“给我绝对最新值”肯定会始终返回该值,直到发生另一次更新。您可以执行我提到的条件更新操作,以防止同时写入者相互踩踏。这似乎并不完全符合该作者定义的乐观或悲观类别,因为更新会同步复制到法定人数,但在最新的 Paxos 轮次中未投票的副本可能仍然能够回答一些查询。该方案可能非常复杂,但...