MySQL分片方法?

she*_*eki 85 mysql sharding

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

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

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

Iso*_*opp 108

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

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

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

写案例是a)写入频率永久地超载此服务器磁盘或b)存在太多写入,因此复制永久滞后于此复制层次结构.

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

只有当你需要打碎时才会这样做.


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

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

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

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

您会产生大量网络延迟.

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

在分片环境中,通过在网络上运行对多个节点的键值访问(希望通过批量键访问而不是每次往返的单独键查找)或通过将WHERE子句的一部分向前推送到可以在其中进行的节点来解析查询应用(称为'条件下推'),或两者兼而有之.

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

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

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

MySQL没有API允许异步查询处于正常工作状态.

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

前提条件是异步通信API,MySQL不具备良好的工作形式.另一种选择是在儿童过程中进行大量分叉和连接,这是在季节通行证中访问吮吸的世界.


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

如果你想自动分片(例如通过哈希主键确定哪一行进入哪个节点),或者你想以手动方式进行功能分割("与xyz用户故事相关的表格转到此master,而abc和def相关表转到那个master").

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

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

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


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

  • 我还没有遇到一个分片应用程序,无论是否商业化,它成功地隐藏了数据现在分散在整个网络中的事实,并且由于缺少延迟引起的等待而导致延迟或不一致.如果您是分片,您的应用程序将注意到并需要更改.你也可以自己控制它.没有银弹,但有很多蛇油. (3认同)
  • 这是一个很好的答案.但我想指出,分片实际上只是大批量应用程序所需要的,而且它们可能会产生某种收入.第三方分片应用程序将处理您对连接,跨分片事务等所有的顾虑.如果您得到一个好的,它将保持"关系"数据库的完整性.其他应用程序,你是对的,将简单地将你的数据库变成一个键值对,从而破坏了SQL的目的. (2认同)
  • @Gigala 好吧,花时间撰写这样一个明确的答案,无论其广泛性如何,也没有必要,但我很高兴它完成了,因为这个答案已被证明对我有帮助。请不要阻止用户在回答时不要“跳出框框思考”。 (2认同)

cha*_*man 11

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

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

  3. 这和#2真的一样.


小智 7

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

这个领域的几个新项目:

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


And*_*lov 6

当然是应用级别。

我在这本书中找到的最好的方法

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

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

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

  • 书籍..为什么不在这里解释一下呢。 (4认同)

yur*_*s87 6

截至 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) );
Run Code Online (Sandbox Code Playgroud)

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

一个非常重要的限制:

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


Jus*_*art 5

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

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