MySQL分片方法?


88

分片MySQL表的最佳方法是什么。我能想到的方法是:

  1. 应用程序级别分片?
  2. 在MySQL代理层进行分片?
  3. 中央查找服务器用于分片吗?

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

Answers:


115

分片MySQL表不这样做的最好方法,除非这样做是完全不可避免的。

在编写应用程序时,通常希望以最大化速度和开发者速度的方式进行编写。仅在必要时才对延迟(直到准备好答案的时间)或吞吐量(每时间单位的答案数)进行优化。

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

写的情况是a)写入频率使该服务器磁盘永久过载,或者b)正在进行过多的写操作,因此复制永久滞后于此复制层次结构中。

分片的读取情况是数据的大小太大,以致其工作集不再适合内存,并且数据读取开始击中磁盘,而不是大部分时间从内存中获取数据。

仅在必须分片时才这样做。


分片后,您会以多种方式为此付费:

您的大部分SQL不再是声明性的。

通常,在SQL中,您是在告诉数据库所需的数据,然后将其留给优化器以将其转换为数据访问程序。这是一件好事,因为它很灵活,而且因为编写这些数据访问程序是无聊的工作,会损害速度。

在分片环境中,您可能正在将节点A上的表与节点B上的数据连接起来,或者在节点A和B上具有比节点大的表,并将来自该表的数据与节点B和C上的数据连接起来。为了解决该问题,您开始手动编写基于应用程序端的基于哈希的连接解析(或者您正在重塑MySQL集群),这意味着您最终会得到很多不再声明性的SQL,而是以过程方式表达SQL功能的SQL。 (例如,您在循环中使用SELECT语句)。

您将招致很多网络延迟。

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

在分片环境中,可以通过以下方式解决查询:在网络上对多个节点运行键值访问(希望通过批量键访问,而不是每次往返都进行单个键查找),或者通过将WHERE子句的一部分向前推到可以进行访问的节点上或同时应用(称为“条件下推”)。

但是,即使在最好的情况下,这也要涉及比本地情况更多的网络往返,并且更加复杂。尤其是由于MySQL优化器对网络延迟一无所知(好吧,MySQL群集正在慢慢变得更好,但是对于群集之外的原始MySQL来说仍然如此)。

您正在失去大量的SQL表达能力。

好的,这也许不太重要,但是外键约束和其他SQL数据完整性机制无法跨越多个分片。

MySQL没有API允许按工作顺序进行异步查询。

当相同类型的数据驻留在多个节点上(例如,节点A,B和C上的用户数据)时,通常需要针对所有这些节点解析水平查询(“查找90天未登录的所有用户帐户”或者更多”)。数据访问时间随节点数线性增长,除非可以并行请求多个节点并且结果随输入而汇总(“ Map-Reduce”)。

前提条件是异步通信API,对于MySQL来说,它尚不具备良好的工作状态。另一种选择是在子过程中进行大量分叉和建立联系,这正在访问整个季节过程。


一旦开始分片,数据结构和网络拓扑将成为您应用程序的性能指标。为了合理地执行性能,您的应用程序需要了解这些内容,这意味着实际上只有应用程序级分片才有意义。

问题是更多的,如果您想自动分片(例如,通过对主键进行散列来确定哪一行进入哪个节点),或者您想以手动方式进行功能拆分(“与xyz用户故事相关的表将转到此主表,而与abc和def相关的表将转到该主表”)。

功能分片的优势在于,如果操作正确,大多数时候大多数开发人员都看不到它,因为与用户故事相关的所有表都可以在本地使用。这使他们仍然可以尽可能长时间地受益于声明式SQL,并且由于跨网络传输的次数保持最小,因此还可以减少网络延迟。

功能分片的缺点是它不允许任何单个表都大于一个实例,并且需要设计人员的手动注意。

功能分片的优点是,相对容易地对现有代码库进行了很多更改,但变化不算太大。在过去的几年中,http://Booking.com做了多次,对他们来说效果很好。


说了这么多,看着你的问题,我相信你在问错问题,或者我完全误解了你的问题陈述。


2
这是一个很好的答案。但我想指出的是,分片实际上仅适用于大量应用程序,并且它们有可能产生某种收益。第三方分片应用程序将处理与连接,跨分片事务等有关的所有问题。如果您获得了满意的解决方案,它将保持“关系”数据库的完整性。没错,其他应用程序会将数据库简单地转换为键值对,从而破坏了SQL的目的。
chantheman 2011年

3
我还没有遇到过分片应用程序(无论是否商用),都可以成功地隐藏这样一个事实,即数据现在分散在整个网络中,并且由于缺少等待时间引起的等待而遭受了等待时间或不一致。如果要分片,您的应用程序将引起注意,并且需要进行更改。您最好自己控制。没有银弹,但是有很多蛇油。
Isotopp

1
您应该签出dbShards。与您添加的“碎片”数量相比,它的伸缩性要好于线性伸缩。您将需要在应用程序端进行很少的更改(如果有的话),是的,您的应用程序不知道区别。它只是发送和获取事务,就像使用ODBC或JDBC一样。如果要对事务进行更多控制,dbShards还允许分片提示。您可以确切地告诉dbShards您要从中读取或写入的碎片。
chantheman 2011年

1
@Gigala很好,也不必花时间编写一个定义明确的答案,而不论其广泛性如何,但我很高兴做到了,因为事实证明该答案对我有帮助。请在回答时不要劝阻用户不要“跳出框框思考”。
mewm '16

12
  1. 应用程序级别分片:dbShards是我所知道的唯一一种“应用程序感知分片”的产品。网站上有一些不错的文章。就像定义一样,应用程序感知分片将更加高效。如果应用程序确切地知道要去哪里进行事务而不必查找它或由代理重定向,那么它本身将更快。当有人正在研究分片时,速度通常是首要考虑的问题之一,即使不是唯一考虑的问题。

  2. 有些人通过代理进行“分片”,但是在我看来,这无法达到分片的目的。您只是在使用另一台服务器来告诉您的交易,在哪里可以找到数据或在哪里存储数据。通过应用程序感知分片,您的应用程序可以知道自己要去哪里。效率更高。

  3. 确实与#2相同。


生产中使用的dbShards在哪里?而且它不是开源的。
sheki 2011年

如果代理是基于哈希而不是基于数据库或存储来查找的,则方法2和3可能也会有所不同。
sheki 2011年

1
dbShards具有各种客户端,但是没有,它不是开源的。我认为您不会找到一个好的开源分片产品。是的,您是对的,可以将哈希用作查找是正确的,但是在那种情况下,您仍然必须再执行一次“停止”操作才能将事务发送到数据库。这就是为什么“应用程序感知”分片几乎总是更快的原因。
chantheman 2011年

但是,就像我说的那样,如果您可以获得维护关系完整性的分片应用程序,那么您将处于良好状态。我提到dbShards,因为它是我所知道的唯一一个。既然如此,它将线性地扩展您的写入和读取速度。您添加4个“碎片”,或者将一台MySQL服务器拆分为4个,它将以4倍的速度运行。
chantheman 2011年

7

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

这个领域中的几个新项目:

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

5

分片查询是用于MySQL的基于OLAP的分片解决方案。它允许您定义分片表和未分片表的组合。未分片的表(例如查找表)可以自由地与分片的表连接,并且分片的表可以彼此连接,只要这些表通过分片键进行连接即可(无交叉分片或跨分片边界的自连接)。作为OLAP解决方案,Shard-Query通常具有100ms或更短的最小响应时间,即使对于简单查询也是如此,因此它不适用于OLTP。分片查询旨在并行分析大数据集。

OLTP分片解决方案也适用于MySQL。封闭源解决方案包括ScaleDBDBShards。开源OLTP解决方案包括JetPantsCubridFlock / Gizzard(Twitter基础架构)。


3

应用水平当然。

这本书中我发现过的最好的方法

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

简短说明:您可以将数据分成许多部分,并在每台服务器上存储约50个部分。这将帮助您避免分片的第二大问题-重新平衡。只要将它们中的一些移到新服务器上,一切就可以了:)

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


您推荐的书已有8年历史了...它涵盖了与当今技术相关的分片吗?
拉菲安2012年

1
它涵盖了一些扩展mysql的基本方法。AFAIK在扩展mysql方面没有任何变化。如今,广泛使用相同的应用程序级分片和复制技术。
安德烈·佛罗洛夫

我可能是错的,但是过去一周我一直在对此进行大量研究,而且看起来mySQL本身在过去8年中进行了很多更改,尤其是在分区和缓存方面。今年有一个新版本发布:amazon.com/High-Performance-MySQL-Optimization-Replication/dp/…我没有看过,但我认为它涵盖了可用的新复制模型。
NateDSaint 2012年

4
书..为什么不在这里解释。
DDD

2

截至2018年,似乎有一个MySql本机解决方案。实际上至少有2个-InnoDB集群NDB集群(有商业版本和社区版本)。

由于大多数使用MySql社区版的人对InnoDB引擎更加熟悉,因此应首先探索这一点。它支持开箱即用的复制和分区/分片,并且基于MySql Router提供不同的路由/负载平衡选项。

创建表的语法需要更改,例如:

    CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );

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

一个非常重要的限制:

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


请注意,如果您有日期范围,PARTITION BY HASH(YEAR...)它将扫描所有分区。uck
瑞克·詹姆斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.