本文由云+社区发表做者:腾讯云数据库算法
任何看到显著增加的应用程序或网站,最终都须要进行扩展,以适应流量的增长。以确保数据安全性和完整性的方式进行扩展,对于数据驱动的应用程序和网站来讲十分重要。人们可能很难预测某个网站或应用程序的流行程度,也很难预测这种流行程度会持续多久,这就是为何有些机构选择“可动态扩展的”数据库架构的缘由。数据库
在这篇概念性文章中,咱们将讨论一种“可动态扩展的”数据库架构:分片数据库。近年来,分片(Sharding)一直受到不少关注,但许多人并无清楚地了解它是什么,或者对数据库进行分片可能有意义的场景。咱们将讨论分片是什么,它的一些主要优势和缺点,以及一些常见的分片方法。缓存
下方是本文目录,帮助您接下来的阅读安全
分片(Sharding)是一种与水平切分(horizontal partitioning)相关的数据库架构模式——将一个表里面的行,分红多个不一样的表的作法(称为分区)。每一个区都具备相同的模式和列,但每一个表有彻底不一样的行。一样,每一个分区中保存的数据都是惟一的,而且与其余分区中保存的数据无关。服务器
从水平切分(horizontal partitioning)与垂直切分(vertical partitioning)的关系,可能会有所帮助。在垂直切分表中,全部的列被分离出来,并放入新的不一样的表中。每一个垂直切份内的数据,独立于全部其余分区中的数据,而且每一个分区都包含不一样的行和列。下图说明了如何在水平和垂直方向上对表进行分区:网络
添加描述架构
分片(Sharding)将一个数据分红两个或多个较小的块,称为逻辑分片(logical shards)。而后,逻辑分片(logical shards)分布在单独的数据库节点上,称为物理分片(physical shards)。物理分片(physical shards)能够容纳多个逻辑分片(logical shards)。尽管如此,全部分片中保存的数据,共同表明整个逻辑数据集。分布式
数据库分片(Database shards)是无共享架构的一个例子。这意味着分片是自治的:分片间不共享任何相同的数据或服务器资源。可是在某些状况下,将某些表复制到每一个分片中做为参考表是有意义的。例如,假设某个应用程序的数据库依赖于重量测量的固定转换率。经过将包含必要转换率数据的表复制到每一个分片中,有助于确保查询所需的全部数据都保存在每一个分片中。函数
一般,分片(Sharding)在应用程序级别进行实现。这意味着应用程序包含“要向哪一个分片发送读和写”的代码。可是,某些数据库管理系统内置了分片功能,容许您直接在数据库级别实现分片。性能
以上是分片(Sharding)的概述,接下来让咱们来看一下,这种数据库架构的优势和缺点。
数据库分片的主要吸引力在于,它能够帮助促进水平扩展(horizontal scaling),也称为向外扩展(scaling out)。水平扩展是将更多的机器添加到现有堆栈中,以分散负载,容许更多的流量和更快的处理。这一般与垂直扩展(vertical scaling)造成对比,垂直扩展也称为向上扩展(scaling up),是指升级现有服务器的硬件,一般是添加更多内存或CPU。
让一个关系数据库在单个机器上运行,并按需升级其服务器资源进行向上扩展是相对简单的。但最终,任何非分布式数据库在存储和计算能力方面都会受到限制,所以能够自由地水平扩展数据库,会使您的架构更加灵活且适应性强。
选择分片数据库架构的另外一个缘由,是为了加速查询响应的时间。当您对还没有分片的数据库提交查询时,必须先搜索您查询的表中的每一行,而后才能找到您要查找的结果集。对于具备大型单片数据库的应用程序,查询可能变得极其缓慢。可是,经过将一个表分红多个,查询过程会遍历更少的行,而且返回结果集的速度要快得多。
分片还能够经过减小宕机(outage)的影响,使应用程序更稳定可靠。若是您的应用程序或网站依赖于未分片的数据库,则宕机可能会致使整个应用程序不可用。可是,对于分片数据库,宕机可能只会影响单个分片。即便这可能使某些用户没法使用应用程序或网站部分功能,但仍会低于整个数据库崩溃带来的影响。
虽然对数据库进行分片可使扩展更容易并提升性能,但它也可能会带来某些限制。在这里,咱们将讨论其中的一些限制,以及为何这些限制会让咱们避免对数据库所有分片。
正确实现分片数据库架构,是十分复杂的,因此这是分片遇到的第一个困难。若是操做不正确,则分片过程可能会致使数据丢失或表损坏,这是一个很大的风险。可是,即便正确地进行了分片,也可能对团队的工做流程产生重大影响。与从单个入口点访问和管理数据不一样,用户必须跨多个分片位置管理数据,这可能会让某些团队存在工做混乱。
在对数据库进行分片后,用户有时会遇到的一个问题是分片最终会变得不平衡。举例来讲,假设您有一个数据库,其中有两个单独的分片,一个用于姓氏以字母A到M开头的客户,另外一个用于名字以字母N到Z开头的客户。可是,您的应用程序为姓氏以字母G开头的人提供了过多的服务。所以,A-M分片逐渐累积的数据比N-Z分片要多,这会致使应用程序速度变慢,并对很大一部分用户形成影响。A-M分片已成为所谓的数据热点。在这种状况下,数据库分片的任何好处都被慢速和崩溃抵消了。数据库可能须要修复和从新分片,才能实现更均匀的数据分布。
另外一个主要缺点是,一旦对数据库进行了分片,就很难将其恢复到未分片的架构。分片前数据库的备份数据,都没法与分片后写入的数据合并。所以,重建原始的非分片架构,须要将新的分区数据与旧备份合并,或者将分区的数据库转换回单个数据库,这两种方法都是昂贵且耗时的。
要考虑的最后一个缺点是,并非每一个数据库引擎自己都支持分片。例如,尽管能够手动分片PostgreSQL数据库,但PostgreSQL自己并不包括自动分片功能。有许多Postgres分支包括自动分片功能,但这些分支一般落后于最新的PostgreSQL版本,而且缺少某些其余的功能特性。一些专业的数据库技术——如MySQL Cluster或某些数据库即服务产品(如MongoDB Atlas)确实包含自动分片功能,但这些数据库管理系统的普通版本却并不包含。所以,分片一般须要“本身动手”的方法。这意味着一般很难找到有关分片或故障排除技巧的文档。
如今咱们已经介绍了一些分片的缺点和好处,咱们将讨论一些分片数据库的不一样架构。
一旦你决定对数据库进行分片,接下来你须要弄清楚的是如何进行分片。在运行查询或将传入的数据分发到分片表或数据库时,关键是要将其分配到正确的分片。不然,它可能致使数据丢失或查询速度缓慢。在本节中,咱们将介绍一些常见的分片架构,每一个架构使用稍微不一样的流程来跨分片分发数据。
添加描述
为了确保数据记录以正确的方式被放置在正确的分片中,哈希函数中输入的值都应该来自同一列。此列称为分片键。简单来讲,分片键与主键相似,由于它们都是列,用于为各个行创建惟一标识符。通常来讲,分片键应该是静态的,这意味着它不该包含可能随时间变化的值。不然,它会增长更新操做的工做量,并可能下降性能。
虽然基于键的分片是一种至关常见的分片架构,但在尝试动态添加或删除数据库中的其余服务器时,它会使事情变得棘手。在添加服务器时,每一个服务器都须要一个相应的哈希值,而且许多现有条目(若是不是所有)都须要从新映射到新的正确哈希值,而后迁移到相应的服务器。当您开始从新平衡数据时,新旧哈希函数都不会有效。所以,在迁移期间,您的服务器将没法编写任何新数据,您的应用程序可能会停机。
这种策略的主要吸引力在于,它能够用于均匀分布数据,从而防止热点。此外,因为它以算法方式分配数据,所以无需维护全部数据所在位置的映射,而其余策略(如范围或基于目录的分片)必须维护数据位置的映射。
基于范围的分片(Range based sharding),基于给定值的范围进行数据分片。为了说明,假设您有一个数据库,用于存储零售商目录中全部产品的信息。您能够建立一些不一样的分片,并根据每一个产品的价格范围分配每一个产品的信息,以下所示:
添加描述
基于范围的分片的主要好处是,它实现起来相对简单。每一个分片都包含一组不一样的数据,但它们都具备相同的模式,以及原始数据库。应用程序代码只读取数据所属的范围,并将其写入相应的分片。
另外一方面,基于范围的分片并不能预防数据不均匀分布的现象,而有可能会出现前面提到的数据热点现象。查看示例图,即便每一个分片拥有相同数量的数据,特定产品比其余产品得到更多关注的可能性也会很大。相应的,各个的分片将接收不成比例的读取操做。
要实现基于目录的分片,必须建立并维护一个查找表,该查找表使用分片键来跟踪哪一个分片包含哪些数据。简而言之,查找表是一个表,其中包含有关能够找到特定数据的静态信息集。下图显示了基于目录的分片的简单示例:
添加描述
此处,Delivery Zone列被定义为分片键。未来自分片键的数据,连同每一行应该写入的分片写入查找表。这与基于范围的分片相似,但不是肯定分片键的数据落入哪一个范围,而是将每一个键绑定到其本身的特定分片。若是分片键的基数很低,而且分片键存储键的范围没有意义,那么基于目录的分片比基于范围的分片要更好。请注意,它也不一样于基于密钥的分片,由于它不经过散列函数处理分片键; 它只是根据查找表检查键值,以查看数据须要写入的位置。
基于目录的分片的主要吸引力在于其灵活性。基于范围的分片架构只能指定键值范围,而基于键的分片架构只能使用固定的哈希函数,如前所述,在之后更改该函数很是困难。另外一方面,基于目录的分片容许您使用任何系统或算法将数据项分配给分片,使用这种方法动态添加分片也相对容易。
虽然基于目录的分片是这里讨论的最灵活的分片方法,可是在每次查询或写入以前链接到查找表,可能会对应用程序的性能产生不利影响。此外,查找表可能出现单点故障:若是查询表损坏或出现其余故障,它可能会影响数据库写入新数据或访问现有数据的能力。
是否应该实现分片数据库架构,几乎老是一个争论的问题。有些人认为分片对于达到必定规模的数据库来讲,是不可避免的结果。而另外一些人则认为这是一个使人头疼的问题,除非绝对必要,不然应该避免,由于分片增长了操做的复杂性。
因为这种增长的复杂性,一般仅在处理很是大量的数据时才执行分片。如下是一些常见方案,可能对数据库分片的操做有所帮助:
· 应用程序数据量增加到超过单个数据库节点的存储容量。
· 对数据库的读写量,超过单个节点或其只读副本能够处理的量,从而致使响应时间增长或超时。
· 应用程序所需的网络带宽,超过单个数据库节点和任何只读副本可用的带宽,从而致使响应时间增长或超时。
在分片以前,您应该用尽全部其余选项来优化数据库。您可能须要考虑的一些优化包括:
设置远程数据库。若是您使用的是一个总体应用程序,其中全部组件都位于同一个服务器上,那么能够经过将数据库移到它本身的机器上来提升数据库的性能。因为数据库的表保持不变,所以这不会增长分片的复杂性。可是,它仍然容许您垂直伸缩数据库,使其与基础结构的其余部分分离。
实现缓存。若是您的应用程序的读取性能致使您遇到麻烦,那么缓存是一种能够帮助改进它的策略。缓存涉及临时存储已在内存中请求的数据,以便您之后更快地访问它。
建立一个或多个只读副本。另外一种有助于提升读取性能的策略,包括将数据从一个数据库服务器(主服务器)复制到一个或多个从服务器。在此以后,每次新的写操做在复制到从服务器以前都要先到主服务器,而读操做只对从服务器进行。像这样分发读写能够防止任何一台机器承担过多的负载,从而有助于防止速度降低和崩溃。请注意,建立读副本须要更多的服务器资源,所以花费更多的钱,这对一些人来讲多是一个很大的限制。
升级到更大的服务器。在大多数状况下,将一个数据库服务器扩展到具备更多资源的计算机比分片须要更少的工做量。与建立只读副本同样,具备更多资源的服务器升级可能会花费更多的钱。所以,只有当它确实是您的最佳选择时,您才应该进行服务器扩容。
请记住,若是您的应用程序或网站增加超过某个点,这些策略自己都不足以提升性能。在这种状况下,分片可能确实是您的最佳选择。
对于那些但愿横向扩展数据库的人来讲,分片是一个很好的解决方案。可是,它还会增长不少复杂性,并为您的应用程序建立更多潜在的故障点。分片对于某些人来讲多是必要的,可是建立和维护分片架构所需的时间和资源可能会超过对其余人的好处。
经过阅读这篇概念性文章,您应该更清楚地了解分片的优缺点。接下来,您可使用这些看法来对分片数据库架构是否适合您,作出更明智的决定。
版权声明:本文由腾讯云数据库产品团队整理,页面原始内容来自于db weekly英文官网,若转载请注明出处。翻译目的在于传递更多全球最新数据库领域相关信息,并不意味着腾讯云数据库产品团队赞同其观点或证明其内容的真实性。若是其余媒体、网站或其余任何形式的法律实体和我的使用,必须通过著做权人合法书面受权并自负所有法律责任。不得擅自使用腾讯云数据库团队的名义进行转载,或盗用腾讯云数据库团队名义发布信息。
此文已由腾讯云+社区在各渠道发布
获取更多新鲜技术干货,能够关注咱们腾讯云技术社区-云加社区官方号及知乎机构号