4

我正在尝试建立自己的分片策略,如下所示。假设我有一个 BOXES 和 ITEMS 表,每个盒子可以有几个项目。我将与同一个 BOX 相关的项目放在一台机器中。

box_id 主键包含:server_type(ex. 100) + shard_id+total_amount_of_boxes_per_user

存储在每个用户的total_amount_of_boxes_per_user用户数据库中,每次用户插入一个新框时,我都会将其递增一。

服务器类型 100 将与存储 box+items 数据的服务器列表对齐。这个 server_type->shard 关系列表应该在一个中心位置,我考虑将它作为文档存储在 DynamoDB 中。

DynamoDB 上的配置文档:

boxitems_servers[
 {shard_id: 1,  is_locked: false, hostname: 127.0.0.1}
 {shard_id: 2, is_locked: false, hostname: 127.0.0.2}
 {shard_id: 3, is_locked: false, hostname: 127.0.0.3}
 {shard_id: 4, is_locked: false, hostname: 127.0.0.4}
]

我为我的数据库和我的应用程序层建模,所以我不需要进行连接。最多,我将对数据库进行几次查询,但这些查询将被缓存在服务器和客户端。我正在使用 MySQL 并在 ASP.NET 4.5 中开发我的应用程序

当用户点击页面时:

http://domain.com/1000014294967295

我可以读取该数据,将其拆分并获得以下信息:

  • server_type = 100
  • shard_id = 001
  • total_amount_of_boxes_per_user = 4294967295(当然可以少得多,但它是一个整数值)

我从 DynamoDB 中获取 boxitems_servers 文档,并且仅获取 server_type 的文档。所以server type 100 = boxitems_servers

我根据主机名(凭据在 web.config 中)建立与分片的连接,并根据主键查询数据1000014294967295

is_locked: true我可以通过放入配置文档来决定锁定一个特定的分片。因此,当写入数据(不更新)时,它只会写入未锁定的分片。

我将在 shard_id % number_of_active_shard 上使用 MODULU 写入数据,以将数据均匀地分布在多个分片上。

现在,如果我想添加另一个 Amazon RDS 数据库以进行水平扩展,我只需通过我之前创建的 Amazon AMI 创建具有相同架构的数据库,并将服务器添加到分片列表中。

boxitems_servers[
 {shard_id: 1,  is_locked: false, hostname: 127.0.0.1}
 {shard_id: 2, is_locked: false, hostname: 127.0.0.2}
 {shard_id: 3, is_locked: false, hostname: 127.0.0.3}
 {shard_id: 4, is_locked: false, hostname: 127.0.0.4}
 {shard_id: 4, is_locked: false, hostname: 127.0.0.5} <- NEW ONE
]

Amazon RDS 已经具有复制功能,因此我无需担心。返回/恢复也很容易。

我唯一担心的是:

  • 从不同的分片读取分页数据,考虑到数据分布不均匀
  • 检索排序数据

我需要什么:我想要你对那个策略的看法。我想制作某种即插即用架构,我可以使用 Amazon RDS 并通过添加更多机器和更新配置文件轻松扩展。这应该可以在没有任何停机时间的情况下即时运行。

我不想为所有那些昂贵的解决方案支付数千美元。我相信我可以构建一个很好的分片解决方案来满足我的应用程序需求,它有一些表和那些已经去规范化以防止连接的表。Amazon RDS 已经提供了我需要的复制。

我还可以创建逻辑分片,每个 shard_id 可以更改为指向另一台数据库机器(IP 地址),但是当我查询“叶子”时,如果在那里找不到数据,我需要向上移动并查询其他分片,直到我找到数据。

我认为这可以导致一个好的分片策略,它有其局限性,但可以很好地用于高流量网站(我认为)。

4

1 回答 1

4

我不认为 MOD 策略是最好的策略,因为如果添加节点,则必须将每条记录移动到不同的数据库(我理解这是一个不好的选择)。

一个更好的选择(比如 Cassandra)是散列密钥并将整个密钥空间分成块。

例如,如果哈希以十六进制给出 0 到 FFFF 之间的答案(这应该是完整的 md5 或 sha1)

  • 节点 1 中从 0 到 0FFF。
  • 节点 2 中从 1000 到 4FFF
  • 节点 3 中从 5000 到 8FFF
  • 从 9000 到节点 4 中的 CFFF
  • 从节点 5 中的 D000 到 FFFF

这样您就可以查找单个寄存器,仅在该节点上请求,如果您需要更多寄存器,则最终可能会请求所有节点。取决于您选择什么作为定位数据的关键(它不需要匹配 pk)

如果需要添加更多节点,只需拆分节点 3 中的内容,在上面的示例中,从 5000 到 6FFF 留在节点 3 中,从 7000 到 8FFF 到新节点 6。

于 2013-03-24T19:37:34.283 回答