本文概述
- 分片基础
- MongoDB分片
- MongoDB分片最佳实践
- 总结
虽然大多数人都熟悉灵活的架构, 但它还是处理非常大的数据集的最佳数据库之一(甚至在日常应用程序中甚至是最佳数据库)。尽管该论点的正当性本身需要整篇文章(我希望有一天能找到它的时间!), 但一般的想法是基于SQL的解决方案不支持分片, 并且很难将其构建。
你所希望的最好的办法是创建一个群集(顺便说一句, 它根本上与分片无关)或选择一个托管解决方案, 例如Amazon RDS或Google的Cloud SQL, 它们随着数据的增长而变得昂贵得令人望而却步。
在本文中, 我们将介绍用于水平数据库扩展的一项基本技术:分片(用于MongoDB), 并推荐一些最佳实践。但是, 我觉得最好从分片的基础开始, 因为许多想要扩展MongoDB的人可能对此并不十分熟悉。
但是, 如果你知道分片, 请随时浏览下一节。
分片基础 你可能已经注意到上一节的最后一段中使用了” 水平” 一词。在不进行其他大规模绕行的情况下, 我想快速提出这一点。扩展被考虑为两种类型:要么获得功能更强大, 存储容量更高的计算机(垂直), 要么连接多台较小的计算机并形成一个集合(水平)。
现在, 鉴于即使是目前最好的服务器也没有超过256 GB的RAM或16 TB的硬盘, 当你尝试垂直扩展(或术语” 扩展” )时, 很快就会遇到麻烦。但是, 你可以将尽可能多的单台计算机连接在一起(至少在理论上), 并且可以轻松绕过此限制。
当然, 现在的挑战是在所有这些机器之间进行协调。
数据库分片
术语” 分片” 通常适用于数据库, 其思想是一台机器永远无法容纳所有数据。在分片时, 数据库被” 分解” 为位于不同计算机上的单独的块。一个简单的示例可能是:假设一家企业拥有可以存储多达200万个客户数据项的机器。现在, 该业务已达到该突破点, 并且很快可能会超过250万用户。因此, 他们决定将数据库分为两个部分:
文章图片
神奇的是, 系统容量现在增加了一倍!
好吧, 如果只有生活那么简单! ????
数据库分片中的挑战
一旦你对分片有一些深思熟虑, 一些邪恶的挑战就抬起了他们的头。
没有主键
一旦退出单个数据库, 主键就会失去其含义。例如, 如果你的主键设置为自动递增, 并且将一半的数据移至另一个数据库, 则每个主键现在将具有两个不同的数据项。
【什么是MongoDB分片和最佳实践()】没有外键
由于数据库中不存在指向当前数据库之外的实体的支持(因此, 即使不支持同一台计算机上的其他数据库, 也请不要考虑其他计算机上的数据库), 因此外键的概念不胜枚举。好。突然, 数据库变得” 哑巴” , 数据完整性成为你的问题。
奇怪的数据错误
如果一台机器出现故障, 则可以向最终用户显示” 糟糕, 发生了故障!” 页面, 这无疑会很烦人, 但是一段时间后生活将会步入正轨。
现在考虑在分片数据库中会发生什么。假设在我们之前的示例中, 分片数据库是银行数据库, 并且一个客户向另一个客户汇款。我们还假设第一个客户数据位于第一个分片中, 而第二个客户数据位于第二个分片中(你知道我要怎么处理吗?!)。如果包含第二个分片的计算机发生故障, 你能想象系统将处于什么状态吗?交易资金将去哪里?第一个用户会看到什么?第二个用户会看到什么?当分片重新联机时, 他们俩都会看到什么?
交易管理
让我们还考虑交易管理的日益关键的情况。这次, 假设系统正在100%正常运行。现在, 两个人(A和B)向第三个人(C)付款。这两个交易很可能会同时读取C的帐户余额, 从而引起这种混乱:
- C的帐户余额= $ 100。
- A的交易显示C的余额:$ 100。
- B的交易显示C的余额:$ 100。
- 一笔交易增加了$ 50并更新了余额:$ 100 + 50 = $ 150。
- B的交易增加了$ 50并更新了余额:$ 100 + 50 = $ 150。
传统的SQL系统通过提供内置的事务管理功能使你免于此, 但是, 一旦你退出单台计算机, 你就会感到敬酒。
显然, 使用这样的系统, 很容易遇到数据损坏的问题, 无法恢复。拔头发也无济于事! ????
MongoDB分片 对于软件架构师而言, 对MongoDB的兴奋不仅仅在于其灵活的架构, 还在于其内置的分片支持。仅需连接几个简单的规则和机器, 你就可以立即运行分片的MongoDB集群。
下图显示了在典型的Web应用程序部署中的外观。
文章图片
图片来源:mongodb.com
关于MongoDB分片的最好的部分是, 即使分片平衡也是自动的。那就是说, 如果你有五个分片, 而其中两个几乎是空的, 则可以告诉MongoDB以所有分片均已满的方式重新平衡事物。
作为开发人员或管理员, 你无需担心, 因为幕后的MongoDB承担了大部分繁重的工作。节点的部分故障也是如此;如果你的副本集配置正确并在群集上运行, 则部分中断不会影响系统正常运行时间。
整个说明会变得很简短, 因此在本节结束时, 我将说MongoDB具有一些用于分片, 复制和恢复的内置工具, 使开发人员可以轻松构建大型应用程序。如果你想获得有关MongoDB的分片功能的更全面指南, 可以使用官方文档。
你可能也对该完整的开发者指南感兴趣。
MongoDB分片最佳实践 虽然MongoDB开箱即用就可以” 工作” , 但这并不意味着我们可以固步自封。分片可以永远完成或破坏你的项目, 具体取决于完成的程度。
此外, 还有很多小细节需要说明, 否则, 看到项目崩溃的情况并不少见。这样做的目的不是要吓scar你, 而是要强调计划的必要性, 即使是很小的决定也要格外小心。
分片密钥不可避免地控制着MongoDB中的分片, 因此理想的做法是从此开始调查。
高基数
基数是指变化量。例如, 最喜欢的一百万人口的国家/地区的集合变化很小(世界上只有那么多个国家!), 而其电子邮件地址的集合则具有(完全)高基数。为什么这有关系?假设你选择了一种天真的方案, 该方案可以根据用户的名字对数据进行分片。
文章图片
在这里, 我们有一个相当简单的安排。将扫描传入文档中的用户名, 并根据第一个字母在英语字母中的位置, 将其放入三个分片之一。同样, 搜索文档也很容易:例如, ” Peter” 的详细信息肯定会出现在第二个分片中。
听起来不错, 但重点是, 我们无法控制传入文档用户的姓名。如果大多数时候我们只获得B到F范围内的名字怎么办?如果是这样, 我们将在shard1中包含一个所谓的” 巨型” 块:大多数系统数据都将挤在那儿, 从而将设置有效地转变为一个数据库系统。
治愈?
选择具有高基数的密钥-例如, 用户的电子邮件地址, 或者甚至可以使用复合分片密钥, 它是多个字段的组合。
单调变化
MongoDB分片中的一个常见错误是使用单调增加(或自动增加, 如果需要的话)键作为分片键。
通常, 使用文档的主键。这里的想法很合理, 即随着新文档的不断创建, 它们将平均地落入可用的碎片之一中。不幸的是, 这样的配置是经典的错误。之所以这样, 是因为如果分片密钥总是增加, 则在一个点数据开始在分片的高值侧累积时, 会导致系统不平衡。
文章图片
图片来源:mongodb.com
如你在图像中所见, 一旦我们超过20个范围, 所有文档就会开始在Chunk C中收集, 从而在此处造成整体。解决方案是采用散列分片密钥方案, 该方案通过散列提供的字段之一并使用其确定块来创建分片密钥。
文章图片
图片来源:Mongodb.com
哈希分片键如下所示:
{"_id" :"6b85117af532da651cc912cd"}
。 。 。可以使用以下命令在Mongo客户端外壳中创建:
db.collection.createIndex( { _id: hashedValue } )
早期碎片
直接从战the中走出的最有用的建议之一是尽早分片, 即使你最终得到一个很小的两块集群。一旦数据超过500 GB或更多, 分片就成为MongoDB中一个混乱的过程, 你应该准备好应对令人讨厌的惊喜。此外, 重新平衡过程会消耗大量的网络带宽, 如果你不小心, 可能会阻塞系统。
但是, 并不是每个人都支持分片。作为一个有趣的示例(评论中确实包含了学习内容), 请参见这个不错的Percona博客。
运行平衡器
另一个好主意是监视你的流量模式, 并仅在流量较低时运行分片平衡器。正如我已经提到的, 重新平衡本身会占用相当大的带宽, 这可能会使整个系统快速爬行。请记住, 碎片不平衡不会立即引起恐慌。只需让正常使用情况持续下去, 等待低流量的机会, 然后让平衡器完成其余工作即可!
你可以按照以下方法完成此操作(假设你从凌晨3点到凌晨5点的访问量很少):
use config db.settings.update( { _id: "balancer" }, { $set: { activeWindow : { start : "03:00", stop : "05:00" } } }, { upsert: true } )
总结 分片和扩展任何数据库都是一项艰巨的任务, 但值得庆幸的是, MongoDB使其比其他流行的数据库更易于管理。
确实曾经有一段时间, MongoDB不是任何项目的正确选择(由于它的几个关键问题和默认行为), 但是这些早已不复存在。除了分片, 重新平衡, 自动压缩, 聚合级别的分布式锁定以及许多其他功能外, MongoDB遥遥领先于今天, 是软件架构师的首选。
我希望本文能够阐明MongoDB中的分片方式, 以及扩展规模时开发人员必须注意的事项。要了解更多信息, 你可以获取此在线课程以掌握MongoDB。
推荐阅读
- 从MySQL迁移到MariaDB很容易!
- 推荐下一个项目的前11个开源数据库
- 如何在Ubuntu 18上安装Chromium浏览器()
- 如何安装和基本的MySQL命令示例
- 故障排除(netstat: command not found)
- telnet无法识别为内部或外部命令-已修复
- 7个适用于小型到大型站点的开源Web服务器
- 如何在RHEL / CentOS 7中启动时自动启动服务()
- 如何在Ubuntu,CentOS上安装Node.js 11()