DIY分片策略与Amazon RDS协同工作

时间:2012-10-20 21:12:10

标签: mysql scalability sharding

我正在尝试按如下方式构建自己的分片策略。假设我有一个BOXES和ITEMS表,每个框可以有几个项目。我把与同一个BOX相关的项目放在一台机器上。

box_id主键包含:server_type(例如100)+ shard_id + total_amount_of_boxes_per_user

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

服务器类型100将与存储框+项数据的服务器列表对齐。这个server_type->分片关系列表应该位于一个中心位置,我考虑将它作为文档存储在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地址),但是当我查询'叶子'时,如果我在那里找不到数据,我需要移动up并查询其他分片,直到找到数据。

我认为这可以带来良好的分片策略,这有其局限性,但对于高流量网站(我认为)可以很好地工作。

1 个答案:

答案 0 :(得分:1)

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

更好的选择(就像Cassandra一样)是散列键并将整个键空间分成块。

作为示例,如果hash在十六进制中给出0到FFFF之间的答案(这应该是完整的md5或sha1)

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

这就是你要寻找一个寄存器,你只在那个节点请求,如果你需要更多寄存器,你最终可能会请求所有节点。取决于您选择什么作为定位数据的关键(它不需要匹配PK)

如果你需要添加更多的节点,你只需要拆分你所拥有的节点,例如节点3,在上面的例子中,你从节点3中得到5000到6FFF,从7000到8FFF到达一个新节点6。