MySQL具有在不同服务器上创建数据库副本的内置能力。这可用于许多事情——在服务器之间分担负载、热备份、创建测试服务器和故障转移。
复制的基本设置涉及一个主服务器处理大部分写入操作,一个或多个从服务器仅处理读取操作。更先进的变体是主-主配置,允许同时有几个服务器进行写入,从而扩展写入。
每种配置都有其优缺点,但它们共享的一个问题是复制延迟——由于MySQL复制是异步的,因此并非所有节点始终具有最新数据。这要求应用程序意识到复制并合并具有复制感知的查询以正常工作。对于某些应用程序,这可能不是一个问题,但如果您总是需要最新的数据,则事情会变得相当复杂。
复制需要一些负载均衡来分担节点之间的负载。这可以简单地修改应用程序代码,也可以使用专用软件和硬件解决方案。
分片是一种常用的扩展数据库解决方案的方法。您将数据拆分为较小的片段并将其分布在不同的服务器节点上。这要求应用程序意识到数据存储的修改以有效地工作,因为它需要知道在哪里查找所需信息。
现有抽象框架可用于帮助处理数据分片,例如Hibernate Shards,它是Hibernate ORM的扩展(不幸的是,它是Java的。我使用PHP)。HiveDB是另一种解决方案,它还支持分片重新平衡。
Sphinx是一个全文搜索引擎,可以用于远比测试搜索更多的内容。对于许多查询,它比MySQL快得多(特别是对于分组和排序),可以并行查询远程系统并聚合结果 - 这使得它在与分片一起使用时非常有用。
通常情况下,应该将sphinx与其他扩展解决方案一起使用,以获得更多的可用硬件和基础设施。缺点是,您需要让应用程序代码了解sphinx才能明智地使用它。
扩展解决方案因所需应用程序而异。对于我们和大多数Web应用程序来说,我认为复制(可能是多主)是通过负载均衡器分配负载的方法。针对特定问题区域(巨大表格)进行分片也是水平扩展的必要条件。
我还将尝试Continuent Sequoia,看看它是否能够实现承诺,因为它将涉及对应用程序代码的最小更改。
免责声明:本人未使用过MySQL Cluster,所以我只是根据听到的谈一下。
MySQL Cluster是一种高可用性(HA)解决方案。它很快,因为它全部在内存中,但它真正的卖点是可用性。没有单点故障。另一方面,使用复制,如果主服务器出现故障,则必须实际切换到副本,并且可能会有一小段时间的停机时间。(虽然 DRBD 解决方案是具有高可用性的另一种选择)
集群需要整个数据库都放在内存中。这意味着集群中的每台机器都需要足够的内存来存储整个数据库。因此,这对于非常大的数据库来说不是一个可行的解决方案(或者至少是一个非常昂贵的解决方案)。
我认为除非HA 非常重要(即基本不是),否则更多的麻烦(和金钱)不值得。 复制通常是更好的选择。
编辑: 我忘记还有一点,Cluster不允许外键,并且范围扫描比其他引擎慢。 这里是一个链接,介绍了 MySQL Cluster的已知限制
关于维护drupal.org的人如何构建他们的数据库服务器,有一些很好的讨论:
这两篇文章都是来自2007年,因此现在可能对集群支持更强大,但当时他们选择了复制。
做复制的好处在于它很容易。只需要设置2个mysql盒子,更改第二个盒子上的serverID,然后使用change master to命令将第二个盒子指向第一个盒子即可。
以下是相关的从库my.cnf配置示例:
#
# Log names
#
log-bin=binlog
relay-log=relaylog
log-error=errors.log
#
# Log tuning
#
sync_binlog = 1
binlog_cache_size = 1M
#
# Replication rules (what are we interested in listening for...)
#
# In our replicants, we are interested in ANYTHING that isn't a permission table thing
#
replicate-ignore-db = mysql
replicate-wild-ignore-table=mysql.%
#
# Replication server ID
#
server-id = 2
确保每个从服务器的serverID都增加了1(下一个从服务器是服务器3)。
设置一个用户名和密码,让从服务器可以连接,然后运行:
change master to MASTER_HOST = 'x.x.x.x'; change master to MASTER_PASSWORD = "xxxxx";
以此类推。最后,运行“start slave;”
你的从服务器就启动并开始复制了。不错吧!
这假设你从两个空服务器开始。然后你可以将数据库转储到主服务器上,在主服务器加载时,它也会加载到从服务器上。
你可以通过运行以下命令来检查从服务器的状态:
show slave status \G
玩得开心...太容易了...
在我看来,这里的混淆只会让我回到Mnesia。通过分片、处理索引的声明性和实用性方式、数据库副本的位置透明等等,我们可以使Mnesia更加高效。
在我们的设置中,我们同时运行MySQL Cluster和Mnesia。我们的数据有点季节性。所以经过一段时间后,我们会将不再使用的数据从Mnesia中移除并将其放入MYSQL Cluster中。这样可以保持我们的Mnesia高效。此外,我们还有使用主流语言(如Python、Clojure等)编写的应用程序,直接从MySQL中获取数据。
简而言之,我们在MySQL Cluster上运行Mnesia。MySQL Cluster可以处理大型数据集,一个数据库可以增长到50GB以上。我们使用Mnesia为Erlang/OTP应用程序提供支持。Java和PHP通过定制的REST(最近是Thrift)API使用JSON和XML作为交换格式从Mnesia中访问数据。
数据访问层已经将对Mnesia和旧版MySQL Cluster的数据访问进行了抽象处理,如果需要的话。Mnesia主要用于支持Erlang/OTP应用程序。一旦它被大量数据占用,我们就将其转移到MYSQL Cluster中。数据访问层可以代表所有应用程序访问Mnesia和MySQL中的数据。
我可以说的是,Mnesia对我们来说是最好的选择。表高度分片和索引,查询性能非常好,并且数据库在通过隧道连接的2个位置上进行复制。
早些时候,我们担心由于表大小限制,Mnesia可能无法处理尽可能多的记录。但我们发现这种说法是错误的。通过良好的调整(分片),我们的Mnesia数据库每年可以容纳约2.5亿条记录。
我们从Erlang的复杂数据结构中受益,而且Mnesia可以不加修改地接受它。与其他遗留语言的应用程序相比,Erlang/OTP应用程序最为高效。我们计划将所有系统迁移到Erlang/OTP技术。从Erlang中,我们可以轻松地访问MySQL Cluster中的数据,并在其服务器上执行查询,事实上,我们得出结论:正是由于Erlang的大规模并发性,才能充分利用MySQL服务器资源。
Mnesia在我们的项目中表现非常出色。由于其惊人的性能,Mnesia已经彻底改变了我们看待数据库的方式。在高峰时段,我们的Solaris服务器CPU核心的平均使用率约为48%。
我建议您尝试一下Mnesia,说不定它可以满足您的分发或复制需求。
MySQL集群是一个奇怪的生物,每次我们评估它时,要么表现非常糟糕,要么不可靠。
它的设置非常复杂(至少需要三个节点,可能需要更多)。此外,它没有提供客户端故障转移的功能,因此您必须自己处理(或使用其他代理等作为代理)。
它非常聪明,因为它对主键进行自动哈希分区,从而允许您扩展写入,并且因为它没有单点故障。
但我真的认为它更适合设计用于非常特殊的用途。在大多数情况下,它不能替换另一个数据库引擎(例如InnoDB)的性能或功能。
我没有使用过它们,但从文档中可以看出,如果最大的负载来自于数据库的读取,那么复制是首选的解决方案。
“内存”限制阻止我们将MySQL集群用于近50GB的数据,因此我们使用DRBD加Linux Heartbeat。
这有点像在两个(或更多)盒子之间保持数据库/日志/配置同步的RAID阵列(但仅一个服务器可以处于“活动”状态)。故障转移是自动的,使用相同的IP地址,并且像mysql重新启动一样快,因此这对我们来说是一个好解决方案。