sql server 数据库分片 - 如何处理公共数据/非分片数据

Mat*_*att 12 sql-server

我们有一个非常大规模的企业级数据库。作为我们业务模型的一部分,所有 Web 用户每个月都会在同一时间访问我们的 Web 服务器,这反过来又会影响我们的 sql 框。流量非常大,并且随着公司规模的扩大,流量会继续增长。sql proc优化已经完成,硬件已经扩展到一个非常高的水平。

我们现在正在寻求对数据库进行分片,以确保我们能够处理公司的增长和未来的负载。

我们已经决定应该对哪些特定数据进行分片。它是我们数据库的一个子集,使用率很高。

但是,我的问题是关于常见/通用的非分片数据。像这样的数据示例可能是库存表,也可能是员工表、用户表等。

我看到两个选项来处理这个通用/通用数据:

1) 设计 1 - 将通用/通用数据放在外部数据库中。所有写入都将发生在这里。然后,此数据将被复制到每个分片,允许每个分片读取此数据并在 t-sql procs 中对这些数据进行内部连接。

2) 设计 2 - 为每个分片提供所有通用/通用数据的副本。让每个分片本地写入这些表,并利用 sql 合并复制在所有其他分片上更新/同步此数据。

对设计的担忧 #1

1) 事务性问题:例如,如果您必须在分片中写入或更新数据,然后在 1 个存储过程中写入/更新公共/通用表,您将无法再轻松地做到这一点。数据现在存在于单独的 sql 实例和数据库中。您可能需要使用 MS DTS 来查看是否可以将这些写入包装到事务中,因为它们位于单独的数据库中。性能是这里的一个问题,并且可能涉及写入分片和公共数据的过程的重写。

2) 参照完整性的丧失。无法实现跨数据库参照完整性。

3) 重新编码系统的大面积区域,使其知道将公共数据写入新的通用数据库但从分片读取公共数据。

4)。增加了数据库行程。像上面的#1 一样,当您遇到必须更新分片数据和公共数据的情况时,您将进行多次往返来完成此操作,因为数据现在位于不同的数据库中。这里有一些网络延迟,但我并不像上述 3 那样担心这个问题。

对设计的担忧 #2

在设计#2 中,每个分片都有自己的所有公共/通用数据的实例。这意味着连接到或更新公共数据的所有代码继续像今天一样工作/运行。开发团队几乎不需要重新编码/重写。然而,这种设计完全依赖于合并复制来保持所有分片之间的数据同步。数据库管理员技术精湛,非常担心合并复制可能无法处理这个问题,如果合并复制失败,从这个失败中恢复不是很好,可能会对我们产生非常负面的影响。

我很想知道是否有人选择了设计选项 #2。我也很想知道我是否忽略了我没有看到的第三个或第四个设计选项。

先感谢您。

Bre*_*zar 7

你的问题集中在这个:

但是,我的问题是关于常见/通用的非分片数据。像这样的数据示例可能是库存表,也可能是员工表、用户表等。

当您进行分片时,并且您拥有所有分片都需要查看的数据,您必须使用一些属性对这些数据进行分类:

它经常变化吗?在您的示例中,您列出了库存、员工和用户。通常库存变化非常快,但员工记录仅定期更改(例如,每天更新数百次)。

每个分片可以容忍多少延迟?尽管 Inventory 可能会不断变化,但您通常可以容忍像这样的桌子上的大量延迟(几分钟甚至几小时)。如果您销售的独特商品数量非常有限,而且永远无法补货(想想原创艺术品),那么您根本不会对这些数据进行分片——您只需要查询原始数据库。但是,在大多数在线商店中,您并不是每天都将每件商品都卖光,而且无论如何您都会快速补货,因此您实际上并不需要精确到毫秒的库存计数。事实上,在大多数情况下,您只需要一个 0 或 1 的 In-Stock 标志,然后一个中央进程更新该标志。这样,您就不必将项目计数的每个上/下颠簸都推送到每个分片。另一方面,员工或用户数据,

你会从分片表加入到非分片表吗?理想情况下,这里的答案是否定的 - 您应该进行两个单独的查询来获取数据,然后在应用程序端加入它们。从应用程序的角度来看,这变得更加困难,但它使您能够从每个来源获取最新数据。

这是原始数据还是复制的?思考这个问题的另一种方式:您需要备份什么,多久备份一次?通常在大容量分片环境中,您希望备份尽可能快和尽可能小。(毕竟,您需要保护每个节点,并且希望所有分片在同一时间点故障转移到 DR - 不要让某些分片的数据比其他分片更新。)这意味着分片数据和非分片数据分片数据应该在完全独立的数据库中——即使它们在同一台服务器上。我可能需要对分片(原始)数据进行持续的事务日志备份,但我可能根本不需要备份非分片数据。对我来说,从单一事实来源刷新我的员工或用户表可能更容易,而不是在每个分片上备份它。但是,如果我的所有数据都在一个数据库中,

现在,关于您的担忧:

“交易问题……你将不再能够轻松做到这一点。” 正确的。在分片场景中,将事务的概念抛之脑后。情况也变得更糟 - 对于分片数据,您可以将一个分片启动并联机,另一个分片由于集群实例故障转移或重启而暂时关闭。您需要随时计划系统任何部分的故障。

“无法实现跨数据库引用完整性。” 正确的。当您将单个表拆分到多台服务器上时,您就是在给大男孩穿上裤子并告诉数据库服务器您正在接管一些艰巨的任务,例如时间点备份、表之间的关系以及合并来自多个来源。现在取决于您和您的代码。

“重新编码系统的大部分区域,以便它知道将公共数据写入新的通用数据库,但从分片中读取公共数据。” 这里也正确。这没有简单的按钮,但是一旦您将其内置到应用程序中,您就可以疯狂地扩展。我认为更简单的方法是通过read 拆分应用程序的连接

“增加了数据库行程。” - 是的,如果您将数据分解到多个服务器中,应用程序将不得不更多地接触网络。关键是还要实现缓存,以便可以将其中一些数据存储在成本更低、吞吐量更高、无锁的系统中。最快的查询是您从未进行过的查询。

我还在此处列出了划分多租户数据库的更多优缺点,例如单个分片的性能调优、每个分片的不同备份/恢复策略以及模式部署挑战。