数据分片的原则和经验
本文提供了一些数据分片的一些原则和经验,遵循这些提示,有助于确保数据正确的分片,而不是阻碍你的应用程序的可扩展性。
新的 SaaS 初创公司很少考虑如何扩展他们的应用程序。当然,他们会设想有一天他们会需要扩张,并将纳入计划,但他们很少在早期就为可扩展性设计他们的应用程序。相反,他们更经常关注于完成他们可以销售的功能。
但是,考虑扩展的时间应该在最开始的时候--在你的第一个客户注册你的服务之前。随着公司推出一个又一个的功能,并且客户不断注册,业务就会增长。随着业务的增长,扩展最终成为一个关注点。
当一个新的SaaS服务遇到资源容量限制时,特别是数据访问资源容量,扩展的需要往往变得很明显。通常情况下,不管是什么技术,数据库都太小了,无法满足不断增长的需求,而且无法扩展到一定程度。
无论你使用什么数据库技术,也无论你投入多大的服务器或其他基础设施来给自己留出发展空间,这个问题都会发生。迟早有一天,你会遇到扩展问题。
一旦扩展资源需求变得非常紧迫,并且需要认真做出的扩展决定,进行数据分片:将你的数据划分到多个并行数据库中,每个数据库持有你的业务部分。这通常是被引入的早期解决方案之一,以扩大你的应用程序的扩展能力。把数据分成多个部分,似乎是解决数据资源问题的一个简单解决方案。如果一个数据库太小,无法处理你的流量,让我们试试两个,或三个,或四个!这就是分片。 一旦你将你的应用数据分片,继续使用同样的方法进行扩展似乎非常简单。随着你的流量增长,只需向你的应用添加更多的并行数据库。 让我们仔细看看分片,以及如何用它来解决早期的数据库扩展问题。
1. 分片例子
究竟什么是分片?一个典型的 SaaS 用例涉及到客户与一些应用程序对话,然后利用存储在数据库中的数据。
随着客户数量的增加,应用程序的负载也在增加。通常,通过添加更多的服务器来处理负载,增加应用程序的容量是相对容易的。
然而,一旦你达到一定数量的客户,你的扩展限制突然变成了你的数据库。你的数据库不能有效地处理更多的客户,而你的应用程序最终会出现可用性问题、性能问题和其他问题。这在图1中得到了说明。
一旦你的数据库达到了一定的规模和容量,就很难使它再增长。相反,你可能会选择将数据库分成多个平行的数据库,并在不同的数据库之间划分客户群。
在图2中,我们把客户分成两个独立的数据库,突然间,我们可以毫无问题地处理额外的客户。
每个数据库都包含支持特定客户所需的所有数据,但单个客户被分割在不同的数据库中。
你如何在多个数据库中分割数据,并在应用程序中知道哪个数据库有哪个客户的数据?通常情况下,分片key被用来确定哪个数据库包含一组特定的数据。
通常情况下,这个分片键是诸如客户ID这样的东西。通过将一些客户ID分配到一个数据库,将其他客户ID分配到另一个数据库,你可以将一个特定客户的所有数据放到一个数据库中。这样,对于每个客户来说,一个单一的数据库将被用于所有的客户请求,而且新的客户可以在任何合理的规模下被添加到新的数据库。
2. 分片出错的地方
那么,这种方法有什么问题呢?当你的客户开始增长时,问题就开始了。随着客户开始更多地使用应用程序,他们开始使用更多的存储和消耗更多的资源。突然间,你的一个分片的容量超载了,你需要把一些客户从一个分片卸载到另一个(负载较少的)分片。你必须把所有这些客户的数据,复制到一个新的分片区,然后把他们的客户ID指向新的分片区。
那么,这种方法有什么问题呢?当你的客户开始增长时,问题就开始了。随着客户开始更多地使用应用程序,他们开始使用更多的存储和消耗更多的资源。突然间,你的一个分片的容量超载了,你需要把一些客户从一个分片卸载到另一个(负载较少的)分片。你必须把所有这些客户的数据,复制到一个新的分片区,然后把他们的客户ID指向新的分片区。
这不是一个微不足道的操作。如果你想在不给客户造成任何明显的停机时间的情况下完成它,那就更不简单了。你如何为一个特定的客户移动大量的数据而不影响客户在移动过程中访问应用程序的能力?答案通常涉及到编写自定义工具。这种工具的编写通常是不容易的,执行起来也有风险。图3说明了这个过程,当一个 "大客户 "使一个数据库过载时,你必须把他们转移到另一个较新的数据库。
下一个发生的问题是,当一个客户变得如此之大,以至于它自己需要整个数据库分片。当你处于这种情况时,当这个客户增长得更大一些时,会发生什么?
突然间,你没有地方可以移动这个客户了,你已经达到了另一个扩展极限--你目前的分片策略根本无法处理的极限。
重新分区、重新平衡、倾斜的使用、跨分片报告和分区分析是更多必须处理的问题。然而,需要处理快速变化的数据集大小,以及需要在分片之间移动数据,是高质量分片机制的最大挑战。
3. 分片还是不分片?
如果你不需要分片,就不要分片! 你可以利用其他策略,比如分库分表,即按照服务和功能划分数据,而不是将其切成分片,来处理数据的扩展。
然而,有时分片是不可避免的。所以,如果你必须分片,请记住以下几点:
1) 在需要它们之前就设置好分片
未雨绸缪,根据乐观的规模预测你对分片的需求,并在实际使用需要之前很久进行分片。
2) 仔细选择分片key
你希望你的分片是独立的,但也是很平衡的。使用客户ID 或者 利用ID基因,似乎是个好主意--它允许你轻松地创建独立的数据集--但客户的规模差异很大,基于客户ID的分片平衡可能很麻烦。基于另一种公共资源的分片是可能的,但是具体的答案在很大程度上取决于你的应用程序的业务逻辑和需求。
3) 建立工具来管理分片
你需要这些工具的时间要比你预期的早得多。这些工具需要能够快速有效地将单个分片的元素(客户等)从一个分片透明地转移到另一个分片。这些工具必须能够在扩展事件中快速地重新平衡多个资源,而且你需要分析,以便在分片规模出现偏差时发出警报。
认真研究用其他方法来划分你的数据。考虑将你的数据存储在各个服务和微服务中,而不是集中的数据存储。数据集越小,对分片的需求就越小,在需要时管理分片就越简单和高效。
大多数现代应用都会经历增长--使用量的增长、数据规模和复杂性的增长、应用复杂性的增长,以及管理应用所需的人员数量和组织规模的增长。人们很容易忽视这些增长的挑战,直到为时已晚,然后使用快速和简单的解决方案来解决眼前的需要。但是,当涉及到数据分片时,规划和彻底的执行对于确保这种架构选择是一种扩展的帮助,而不是一种扩展的责任至关重要。
下一章:如何保证 Mysql 和 Redis 数据一致性
在高并发的业务场景下,数据库是用户并发访问压力最大的环节。通常,我们会在数据库前使用 redis 作为缓存,让请求先访问 redis,而不是直接访问 mysql 等数据库。这样可以大大缓解数 ...