MySQL分片方法?

时间:2011-04-04 16:26:44

标签: mysql sharding

Sharding MySQL表的最佳方法是什么? 我能想到的方法是:

  1. 应用程序级别分片?
  2. 在MySQL代理层进行分片?
  3. 用于分片的中央查找服务器?
  4. 你知道这方面有什么有趣的项目或工具吗?

6 个答案:

答案 0 :(得分:105)

分割MySQL表的最佳方法是不要这样做,除非完全不可避免地这样做。

在编写应用程序时,通常希望以最大化速度和开发人员速度的方式执行此操作。您只在必要时优化延迟(答案准备就绪的时间)或吞吐量(每个时间单位的答案数)。

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

写入情况要么是a)写入频率会永久地超载此服务器磁盘,或者b)进行的写入过多会导致复制永久滞后于此复制层次结构。

分片的读取案例是当数据的大小太大以至于其工作集不再适合内存并且数据读取开始命中磁盘而不是在大多数时间从内存中提供。

只有当 要进行分片时,才能执行此操作。


在你破碎的那一刻,你是以多种方式为此付出的代价:

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

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

对于分片环境,您可能正在连接节点A上的表与节点B上的数据,或者您在节点A和B上有一个大于节点的表,并且正在连接来自节点B上的数据的数据你开始手动编写应用程序端基于散列的连接解决方​​案来解决这个问题(或者你正在重新发明MySQL集群),这意味着你最终会得到很多不再声明的SQL,但是它表达了SQL的功能。一种程序方式(例如,你在循环中使用SELECT语句)。

您会遇到大量网络延迟。

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

在分片环境中,通过将网络上的键值访问运行到多个节点(希望通过批量键访问而不是每次往返的单个键查找)或推送部分WHERE来解析查询可以应用它们的节点(称为'条件下推')或两者。

但是即使在最好的情况下,这涉及到更多的本地情况的网络往返,而且更复杂。特别是因为MySQL优化器根本不了解网络延迟(好吧,MySQL集群正在慢慢变得更好,但对于群集之外的群岛仍然是真的)。​​

你正在失去很多SQL的表现力。

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

MySQL没有API允许异步查询处于正常运行状态。

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

前提条件是异步通信API,MySQL不具备良好的工作形式。另一种选择是儿童过程中的许多分叉和联系,这是在季节通行证中访问世界。


一旦开始分片,数据结构和网络拓扑就会成为应用程序的性能指标。为了表现得相当好,您的应用程序需要了解这些内容,这意味着实际上只有应用程序级别分片才有意义。

如果你想自动分片(例如通过散列主键确定哪一行进入哪个节点),或者你想以手动方式进行功能分割,那么问题就更多了("与之相关的表格xyz用户故事转到这个主人,而abc和def相关表转到那个主人")。

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

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

功能分片的优点是,对现有的代码库进行相对容易的处理,其中包含许多不太大的更改。 http://Booking.com在过去几年中已经多次完成,并且对他们来说效果很好。


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

答案 1 :(得分:10)

  1. 应用程序级别分片:dbShards是我所知道的“应用程序感知分片”的唯一产品。网站上有一些好文章。根据定义,应用程序感知分片将更有效。如果一个应用程序确切地知道了一个事务的去向,而不必查找它或被代理重定向,那么它本身就会更快。当某人正在研究分片时,速度通常是主要考虑因素之一,如果不是唯一的问题。

  2. 有些人用代理“粉碎”,但在我看来,这会破坏分片的目的。您只是使用另一台服务器告诉您的交易在何处查找数据或在何处存储数据。通过应用程序感知分片,您的应用程序可以知道自己的位置。效率更高。

  3. 这与#2真的相同。

答案 2 :(得分:7)

  

你知道这方面有什么有趣的项目或工具吗?

这个领域的几个新项目:

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

答案 3 :(得分:4)

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

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

答案 4 :(得分:3)

当然是申请级别。

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

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

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

我强烈建议你购买并阅读“mysql scaling”部分。

答案 5 :(得分:1)

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

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

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

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

(这只是四个partitioning types之一)

一个非常重要的限制:

  

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