如何跨多个服务器可靠地分片数据

How to reliably shard data across multiple servers

我目前正在阅读一些分布式系统设计模式。当您必须处理大量数据(数十亿或多个 peta 字节)时,其中一种设计模式是将其分布在多个服务器或存储单元中。

解决此问题的方法之一是使用一致性哈希。这应该会导致散列中的所有服务器均匀分布。

这个概念相当简单:我们可以只添加新的服务器,只有范围内的服务器会受到影响,如果你丢失服务器,一致性哈希中的其余服务器将接管。这是当哈希中的所有服务器都具有相同数据(在内存、磁盘或数据库中)时。

我的问题是我们如何处理从一致的散列中添加和删除服务器,其中有太多数据以至于无法存储在单个主机上。他们如何确定要存储哪些数据以及不存储哪些数据?

示例:

假设我们有 2 台机器 运行,“0”和“1”。它们开始达到其最大容量的 60%,因此我们决定添加一台额外的机器“2”。现在0号机上的数据有很大一部分要迁移到2号机上。 我们将如何实现自动化,以便在不停机且可靠的情况下发生。

我自己建议的方法 是服务使用一致的散列,机器会知道如何在彼此之间传输数据。当添加新机器时,一致性哈希服务是否会计算受影响的哈希范围。然后通知受影响的机器 受影响的哈希范围,并且他们需要将受影响的数据传输到机器 2。一旦受影响的机器完成数据传输,他们将 ACK 返回到一致的哈希服务。一旦所有受影响的服务完成数据传输,一致性哈希服务将开始向机器 2 发送数据,并通知受影响的机器他们现在可以删除传输的数据。如果我们在每台服务器上都有 peta 字节,这个过程会花费很长时间。我们在那里需要跟踪在传输过程中发生了什么变化,以便我们可以确保在传输之后同步它们,或者我们可以在传输过程中将 write/updates 提交给机器 0 和 2。

我的方法可行,但我觉得来来回回有点冒险,所以我想听听是否有更好的方法。

我们如何实现自动化,以便在不停机且可靠的情况下发生?

这取决于用于存储数据的技术,但是例如在 Cassandra 中,没有 "central" 管理流程的实体,它是这样完成的几乎所有其他东西;通过让节点相互闲聊。新节点加入集群时没有停机时间(但性能可能会受到轻微影响)。

流程如下:

The new node joining the cluster is defined as an empty node without system tables or data.

When a new node joins the cluster using the auto bootstrap feature, it will perform the following operations

- Contact the seed nodes to learn about gossip state.
- Transition to Up and Joining state (to indicate it is joining the cluster; represented by UJ in the nodetool status).
- Contact the seed nodes to ensure schema agreement.
- Calculate the tokens that it will become responsible for.
- Stream replica data associated with the tokens it is responsible for from the former owners.
- Transition to Up and Normal state once streaming is complete (to indicate it is now part of the cluster; represented by UN in the nodetool status).

取自https://thelastpickle.com/blog/2017/05/23/auto-bootstrapping-part1.html

因此当加入节点处于加入状态时,它正在从其他节点接收数据但在过程完成之前尚未准备好读取(Up 状态)。

DataStax 在这方面也有一些 material https://academy.datastax.com/units/2017-ring-dse-foundations-apache-cassandra?path=developer&resource=ds201-datastax-enterprise-6-foundations-of-apache-cassandra