MySQL分片的方法?

99

如何最佳地对MySQL表进行Sharding?我能想到的方法有:

  1. 在应用程序层面进行Sharding?
  2. 在MySQL代理层面进行Sharding?
  3. 为Sharding设置中央查找服务器?

您是否了解该领域中的任何有趣项目或工具?

8个回答

130

除非完全不能避免,否则不要分片MySQL表。

当您编写应用程序时,通常希望以最大化速度和开发人员速度的方式进行。只有在必要时才会优化延迟(答案准备时间)或吞吐量(单位时间内的答案数量)。

只有当所有这些分区的总和不再适合单个数据库服务器实例时,即出现写入或读取问题时,才会对其进行分区,然后将分区分配给不同的主机(=分片)。

写入的情况是要么a)写入频率永久超载了此服务器的磁盘,要么b)有太多的写入正在进行,因此该复制层次结构的复制永久滞后。

读取的情况下,如果数据大小过大,工作集就不再适合存储器,数据读取开始从磁盘而不是大部分时间从内存中提供。

只有在必须分片时才这样做。


一旦分片,您就会以多种方式为其付费:

许多SQL不再声明性。

通常,在SQL中,您告诉数据库要获取哪些数据,并由优化器将该规范转换为数据访问程序。这是件好事,因为它是灵活的,并且编写这些数据访问程序会损害速度。

在分片环境中,您可能正在节点A上连接表与节点B上的数据进行比较,或者拥有大于一个节点的表,在节点A和B上并且正在使用来自节点B和C的数据与其进行比较。因此,您需要手动编写应用程序端基于哈希的联接解决方案以解决该问题(或者是重新发明MySQL集群),因此您最终会得到许多SQL不再声明性但以过程方式表达 SQL功能(例如,您正在循环中使用SELECT语句)。

您将产生大量网络延迟。

通常,SQL查询可以在本地解决,并且优化器了解与本地磁盘访问相关的成本,并以最小化成本的方式解决查询。

在分片环境下,查询可以通过在多个节点之间运行键值访问(希望批量键访问而不是每次往返进行单个键查找)或将 WHERE 子句的部分向前推送到可以应用它们的节点上(这称为“条件推广”)来解决。但即使在最好的情况下,这也涉及比本地情况更多的网络往返,并且更加复杂。特别是由于 MySQL 优化器根本不知道网络延迟(好吧,MySQL 集群正在缓慢改善这一点,但对于集群外的普通 MySQL 仍然如此)。您正在失去 SQL 的很多表达能力。外键约束和其他用于数据完整性的 SQL 机制无法跨越多个分片。MySQL 没有允许异步查询的 API 是可以正常工作的。当同一类型的数据驻留在多个节点上时(例如用户数据驻留在 A、B 和 C 节点上),水平查询通常需要针对所有这些节点解决(“查找所有超过 90 天未登录的用户帐户”)。数据访问时间随着节点数量的增加呈线性增长,除非可以并行请求多个节点并在结果到达时聚合结果(“Map-Reduce”)。这需要一个异步通信 API,而 MySQL 没有具备良好工作状态的异步查询的 API。另一种选择是在子进程中进行大量分支和连接,这使事情变得更加困难。一旦开始分片,数据结构和网络拓扑将成为应用程序的性能点。为了表现得合理,您的应用程序需要意识到这些内容,这意味着真正只有应用程序级别的分片是有意义的。问题更多地是您是否想要自动分片(例如通过哈希主键确定哪行数据进入哪个节点)还是以手动方式功能拆分(“与 xyz 用户故事相关的表转到此主节点,而 abc 和 def 相关表则转到那个主节点”)。

功能分片的优点在于,如果正确实施,它对大多数开发人员来说是不可见的,因为与他们用户故事相关的所有表格都将本地可用。这使得他们在尽可能长的时间内仍然从声明性SQL中受益,并且由于跨网络转移的数量被保持最小,也会产生更少的网络延迟。

功能分片的缺点在于,它不允许任何单个表格比一个实例更大,并且需要设计师手动关注。

功能分片的优点在于,相对容易对现有的代码库进行一些不太大的更改就可以实现。过去几年中,Booking.com 已经多次完成了这项工作,并且效果很好。


话虽如此,在看完你的问题后,我认为你提出了错误的问题,或者我完全误解了你的问题陈述。


3
这是一个很好的回答。但我想指出,分片技术只有在高流量应用程序中才是必要的,而且很可能它们正在产生某种形式的收入。第三方分片应用程序将处理您在连接、跨分片事务等方面所担心的所有问题。如果您选择了一个好的应用程序,它将维护“关系型”数据库的完整性。其他应用程序,您是正确的,会简单地将您的数据库转化为键值对,从而违背了使用SQL的初衷。 - chantheman
3
到目前为止,我还没有遇到过一个分片应用程序(无论是商业的还是非商业的)成功地隐藏了数据现在已经分散到网络中并且由于缺乏延迟引起的等待时间而受到延迟或不一致性的事实。如果你在使用分片技术,你的应用程序会察觉到并需要进行更改。最好让自己来掌控这个过程。虽然并没有银弹,但却有很多伪科技。 - Isotopp
1
你应该看看dbShards。它的扩展性比添加“分片”数量更好。在应用程序方面,你几乎不需要进行任何更改,而且是的,你的应用程序不会感知到差异。它只是像使用ODBC或JDBC一样发送和获取事务。如果你想要更多对事务的控制,dbShards还允许分片提示。你可以告诉dbShards你想从哪个分片读取或写入。 - chantheman
2
@Gigala 嗯,花时间撰写像这样明确定义的答案,无论广度如何,都不是必要的,但我很高兴它被完成了,因为这个答案已经证明对我有帮助。请不要阻止用户在回答时“跳出框架”思考。 - mewm
这个回答现在已经10年了。事情已经发生了。你可能想查看https://en.pingcap.com/和https://vitess.io/中的TiDB。但要为问题提供相对好的通用答案。TiDB是MySQL协议的数据库重新实现。vitess基于(已过时的)MySQL版本加上额外的代码构建。它们非常不同,但都可以作为原始问题的解决方案。 - Isotopp

13
  1. 应用程序级别分片:dbShards是我所知道的唯一一个能够实现“应用程序感知分片”的产品。网站上有几篇很好的文章。仅从定义上来说,应用程序感知分片将更加高效。如果一个应用程序知道在没有查找或被代理重定向的情况下在哪里处理事务,那么这本身就会更快。当某人考虑进行分片时,速度通常是主要问题,如果不是唯一的问题。

  2. 一些人使用代理进行“分片”,但在我看来,这违背了分片的目的。你只是使用另一台服务器告诉你的事务数据在哪里或者存储在哪里。通过应用程序感知分片,你的应用程序自己知道去哪里。更加高效。

  3. 这与#2基本相同。


dbShards 在生产环境中有使用吗?另外它不是开源的。 - sheki
如果代理基于哈希查找而不是数据库或存储进行查找,那么方法2和3也可能会有所不同。 - sheki
1
dbShards正在与各种客户进行生产,但不,它不是开源的。我认为您不会找到一个好的开源分片产品。是的,您是正确的,哈希可以用作查找,但在这种情况下,您仍然需要多走一步才能将事务传递到数据库。这就是为什么“应用程序感知”分片几乎总是更快的原因。 - chantheman
但是就像我说的,如果你能得到一个维护关系完整性的分片应用程序,那么你就会处于良好的状态。我提到 dbShards 是因为它是我所知道唯一可以做到这一点的分片应用程序。而且由于它的存在,它可以使您的写入和读取速度呈线性增长。您添加4个“分片”,或者将您的一个MySQL服务器拆分成4个,它将运行4倍快。 - chantheman

7

你知道这个领域有什么有趣的项目或工具吗?

该领域中有几个新项目:

  • citusdata.com
  • spockproxy.sourceforge.net
  • github.com/twitter/gizzard/

6
截至2018年,似乎有一个MySQL本地解决方案。实际上至少有两个 - InnoDB ClusterNDB Cluster(其中有商业版本和社区版本)。
由于大多数使用MySQL社区版的人更熟悉InnoDB引擎,因此应首先探索它。它支持开箱即用的复制和分区/分片,并基于MySQL路由器提供不同的路由/负载平衡选项。
您表格创建的语法需要更改,例如:
    CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );

(这只是四种分区类型之一)

一个非常重要的限制:

InnoDB外键和MySQL分区不兼容。分区的InnoDB表不能有外键引用,也不能有被外键引用的列。具有或被外键引用的InnoDB表不能进行分区。


请注意,如果您有一个日期范围,PARTITION BY HASH(YEAR...)将扫描_所有_分区。 真糟糕。 - Rick James

6

当然是应用级别的。

我在这本书中发现了最好的方法。

《高性能MySQL》 http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064

简短描述:您可以将数据分成许多部分,并在每个服务器上存储约50部分。它将帮助您避免分片的第二大问题 - 重新平衡。只需将其中一些移动到新服务器,一切都会很好:)

我强烈建议您购买并阅读“mysql扩展”部分。


你推荐的那本书已经出版8年了,它是否涵盖了与今天技术相关的分片技术? - raffian
1
它涵盖了一些基本的方法来扩展MySQL。据我所知,在扩展MySQL方面没有什么改变。同样的应用程序级分片和复制技术现在被广泛使用。 - Andrey Frolov
我可能错了,但是在过去的一周里,我已经进行了大量的研究,看起来mySQL本身在过去8年中进行了很多改变,特别是关于分区和缓存方面。今年推出了一个新版本:http://www.amazon.com/High-Performance-MySQL-Optimization-Replication/dp/1449314287/ref=dp_ob_title_bk/185-6821409-4526615 我还没有阅读它,但我认为它涵盖了可用的新复制模型。 - NateDSaint
4
书籍...为什么不在这里解释呢? - Playdome.io

5

Shard-Query 是一个基于 OLAP 的 MySQL 分片解决方案。它允许您定义一组分片表和非分片表。非分片表(如查找表)可以自由地与分片表连接,只要表是通过分片键连接的,分片表也可以相互连接(不能跨分片或自身连接跨越分片边界)。作为 OLAP 解决方案,Shard-Query 通常具有最小响应时间不超过 100ms,即使对于简单查询也是如此,因此它不适用于 OLTP。Shard-Query 旨在并行分析大型数据集。

MySQL也存在OLTP分片解决方案。闭源解决方案包括ScaleDB, DBShards。开源OLTP解决方案包括JetPants, CubridFlock/Gizzard(Twitter基础设施)。


2

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接