Data Partitioning 数据分区
- 分区方法
- 分区标准
- 数据分区的常见问题
数据分区是一种将大型数据库(DB)分解为许多较小部分的技术。这是在多个计算机之间拆分数据库/表以提高应用程序的可管理性,性能,可用性和负载平衡的过程。进行数据分区的理由是,在一定的扩展点之后,通过添加更多的计算机进行水平扩展比通过添加功能更强的服务器进行垂直扩展更便宜且更可行。
分区方法
- 水平分区 Horizontal partitioning:将不同的行放入不同的表中。例如,如果我们在一个表中存储不同的位置,则可以决定将邮政编码少于10000的位置存储在一个表中,而将邮政编码大于10000的位置存储在单独的表中。这也称为基于范围的分区,因为我们将不同范围的数据存储在单独的表中。水平分区也称为数据分片 Data sharding。
- 垂直分区 Vertical Partitioning:将数据划分为在自己的服务器中存储与特定功能相关的表。例如,如果我们正在构建类似Instagram的应用程序需求是存储与用户,他们上传的照片以及他们所关注的人有关的数据。我们可以决定将用户个人资料信息放置在一个数据库服务器上,将好友列表放置在另一个数据库服务器上,将照片放到第三个数据库服务器上。
垂直分区易于实现,对程序影响小。但主要为题在于:如果应用程序实现了额外的增长,则可能有必要在各个服务器之间进一步划分特定于功能的数据库(例如,单个服务器不可能处理100亿个元数据的所有查询) 1.4亿用户的照片)。 - 基于目录的分区 Directory Based Partitioning:解决上述方案中提到的问题的一种松散耦合的方法是创建一个查找服务,该服务了解您当前的分区方案,并将其从数据库访问代码中抽象出来。因此,要找出特定数据实体所处的位置,我们查询目录服务器,该目录服务器保存着每个元组键与其数据库服务器之间的映射。这种松散耦合的方法意味着我们可以执行诸如将服务器添加到数据库池或更改分区方案之类的任务,而不会影响应用程序。
分区标准
- 基于键或基于散列的分区 Key or Hash-based partitioning:将散列函数应用于要存储的实体的某些键属性;产生分区号。例如,如果我们有100个数据库服务器,并且ID是一个数字值,则每次插入新记录时,该值都会增加1。在此示例中,哈希函数可以是“ ID%100”,这将为我们提供服务器号,我们可以在其中存储/读取该记录。这种方法应确保服务器之间数据的均匀分配。这种方法的根本问题是,它可以有效地修复数据库服务器的总数,因为添加新服务器意味着更改哈希函数,这将需要重新分配数据和服务的停机时间。解决此问题的方法是使用“一致性哈希”。
- 列表分区 List partitioning:每个分区都分配了一个值列表,因此,每当我们要插入新记录时,我们都会看到哪个分区包含我们的键,然后将其存储在其中。例如,我们可以决定将居住在冰岛,挪威,瑞典,芬兰或丹麦的所有用户存储在北欧国家/地区的分区中。
- 循环分区 Round-robin partitioning:这是一个非常简单的策略,可确保数据均匀分配。对于“ n”个分区,“ i”元组被分配给分区(i mod n)。
- 复合分区 Composite partitioning:我们将上述任何分区方案组合在一起以设计新方案。例如,首先应用列表分区方案,然后再应用基于散列的分区。一致的哈希可以认为是哈希和列表分区的组合,其中哈希将键空间减小到可以列出的大小。
分区常见问题
分区数据库上,对可以执行的不同操作有某些额外的约束, 这些限制中的大多数是由于以下事实:跨多个表或同一表中的多行的操作将不再在同一服务器上运行。以下是分区引入的一些约束和其他复杂性:
- 联接和非规范化 Joins and Denormalization: 在运行在一台服务器上的数据库上执行联接(join)很简单,但是一旦数据库被分区并分布在多台计算机上,执行跨越数据库分区的联接(join 操作)通常是不可行的。由于必须从多个服务器编译数据,因此这种联接将不会提高性能。解决此问题的常用方法是对数据库进行非规范化,以便可以从单个表中执行以前需要的联接的查询。当然,该服务现在必须处理所有非规范化的风险,例如数据不一致。
- 参照完整性 Referential integrity: 数据库的参照完整性是指表与表之间的一种对应关系,通常情况下可以通过设置两表之间的主键、外键关系,或者编写两表的触发器来实现。 有对应参照完整性的两张表格,在对他们进行数据插入、更新、删除的过程中,系统都会将被修改表格与另一张对应表格进行对照,从而阻止一些不正确的数据的操作。因此对分区数据库执行跨分区查询是不可行的,类似地,尝试在分区数据库中强制执行数据完整性约束(例如外键)也非常困难。
大多数RDBMS不支持跨不同数据库服务器上的数据库的外键约束。这意味着需要对分区数据库进行引用完整性的应用程序通常必须在应用程序代码中强制实施它。通常,在这种情况下,应用程序必须运行常规的SQL作业以清理悬空的引用。 - 重新平衡 Rebalancing:
- 数据分布不均匀,例如,特定邮政编码的很多地方无法容纳一个数据库分区。
- 分区上的负载很大,例如,专用于用户照片的DB分区正在处理太多请求。
在这种情况下,要么我们必须创建更多的数据库分区,要么必须重新平衡现有分区,这意味着分区方案已更改,所有现有数据都移至了新位置。在不造成停机的情况下做到这一点非常困难。使用基于目录的分区之类的方案确实以增加系统的复杂性和创建新的单点故障(即查找服务/数据库)为代价,使平衡变得更可口。
Indexing 数据库索引
数据库索引(index),是数据库管理系统中的一个排序的数据结构,用于协助快速查询、更新数据库表中的数据。
索引是如何提高查询效率的呢?
通过使用索引,数据库能够快速找出索引列中特定值的那一行;而如果不使用索引,数据库将不得不从第一条记录开始查找相关列的特定值,直到找到对应的那一行为止。在这个过程中,表越大,则可能花费时间就越多。
简单说,如果待查询的列有索引,则数据库就能快速定位到该列的某一个值的位置(并关联出相关记录),而省去了查找无用记录的过程,由此提高了数据查询效率。
Example: 图书馆目录
图书馆目录是一个寄存器,其中包含在图书馆中找到的书籍列表。目录的组织方式类似于数据库表,通常由四列组成:书名,作家,主题和出版日期。通常有两种这样的目录:一种按书名排序,另一种按作者姓名排序。这样,您就可以想到要阅读的作家,然后翻阅他们的书,或者查找您想阅读的特定书名,以防万一您不知道作者的名字。这些目录就像书籍数据库的索引。它们提供了可通过相关信息轻松搜索的数据排序列表。
简而言之,索引是一种数据结构,可以将其视为目录,该目录将我们指向实际数据所在的位置。因此,当我们在表的某个列上创建索引时,我们将该列和指向整个行的指针存储在索引中。让我们假设一个包含书列表的表,下图显示了“标题”列上的索引的样子:
就像传统的关系数据存储一样,我们也可以将此概念应用于更大的数据集。使用索引的技巧是,我们必须仔细考虑用户如何访问数据。如果数据集的大小为数TB,但是有效载荷非常小(例如1 KB),则索引是优化数据访问的必要条件。在如此大的数据集中找到较小的有效载荷可能是一个真正的挑战,因为我们不可能在任何合理的时间内对这么多的数据进行迭代。此外,如此大的数据集很可能分布在多个物理设备上-这意味着我们需要某种方法来找到所需数据的正确物理位置。索引是执行此操作的最佳方法。index索引 处于物理实现层面,如果对表个的任意列建立索引,那么当建立索引的列处于 SQL 语句中的 where 条件中时,就可以进行快速的数据定位,从而实现快速检索。
索引如何降低写入性能?
索引可以极大地加快数据检索的速度,但由于附加键的影响,索引本身可能会很大,这会减慢数据的插入和更新速度。
在为具有活动索引的表添加行或对现有行进行更新时,我们不仅必须写入数据,而且还必须更新索引。这将降低写入性能。这种性能下降适用于表的所有插入,更新和删除操作。因此,应避免在表上添加不必要的索引,并应删除不再使用的索引。重申一下,添加索引是关于提高搜索查询的性能。如果数据库的目标是提供一个经常被写入而很少读取的数据存储,那么在这种情况下,降低更常见的操作(即写入)的性能而提高读的性能可能是不值得。
数据库索引
Proxies 代理
代理服务器类型 Proxy Server Types
代理服务器是客户端和后端服务器之间的中间服务器。客户端连接到代理服务器,以请求诸如网页,文件,连接等服务。简而言之,代理服务器是一种软件或硬件,可充当中介以请求来自其他服务器的客户。
通常,代理用于过滤请求,日志请求或有时转换请求(通过添加/删除头,加密/解密或压缩资源)。代理服务器的另一个优点是其缓存可以处理许多请求。如果多个客户端访问特定资源,则代理服务器可以缓存该资源并将其提供给所有客户端,而无需访问远程服务器。
开放代理 Open Proxy
开放代理是可以被任何互联网用户访问的。通常,代理服务器仅允许网络组中的用户(即封闭代理)存储和转发Internet服务(例如DNS或网页),以减少和控制该组使用的带宽。但是,使用开放代理,Internet上的任何用户都可以使用此转发服务。有两种著名的开放代理类型:
- 匿名代理 Anonymous Proxy:该代理可在同一台服务器上显示信息,但不会公开其IP地址。尽管可以很容易地发现它的代理服务器,但对于某些用户来说却是有益的,因为它们隐藏了IP地址。
- 透明代理 Trаnspаrent Proxy:该代理服务器本身完全可以识别,并且在HTTP支持者的支持下,可以看到第一个IP地址。使用这种服务器的最大好处是可以缓存网站。
反向代理 Reverse Proxy
一个反向代理从一个或多个服务器代表客户端检索资源。然后,这些资源被返回给客户端,好像它们源自代理服务器本身一样。
图解正向代理、反向代理、透明代理
冗余和复制 Redundancy and Replication
冗余是指系统的关键组件或功能的重复,目的是通常通过备份或故障保护的形式来提高系统的可靠性,或提高实际系统的性能。例如,如果在单个服务器上仅存储一个文件的副本,则丢失该服务器意味着丢失该文件。由于丢失数据很少是一件好事,因此我们可以创建文件的重复或冗余副本来解决此问题。
冗余在消除系统中的单点故障方面起着关键作用,并在危机中需要时提供备份。例如,如果我们有两个正在生产中运行的服务实例,而一个实例发生故障,则系统可以故障转移到另一个实例。
复制意味着共享信息以确保冗余资源(例如软件或硬件组件)之间的一致性,以提高可靠性,容错性或可访问性。
复制已在许多数据库管理系统(DBMS)中广泛使用,通常在原始副本与副本之间具有主副本关系。主服务器获取所有更新,然后更新到副本服务器。每个副本输出一条消息,说明已成功接收到更新,因此允许发送后续更新。
SQL vs. NoSQL
- SQL
- NoSQL
- SQL和NoSQL之间的高级差异
- SQL VS NoSQL-使用哪个?
- 使用SQL数据库的原因
- 使用NoSQL数据库的原因
数据库有两种主要类型:
- SQL(关系数据库): 关系数据库是结构化的,并具有预定义的架构,例如存储电话号码和地址的电话簿。**关系数据库将数据存储在行和列中。每行包含有关一个实体的所有信息,每列包含所有单独的数据点。**一些最流行的关系数据库是MySQL,Oracle,MS SQL Server,SQLite,Postgres和MariaDB。
- NoSQL(非关系数据库):非关系数据库是非结构化的,分布式的,并且具有动态模式,例如文件夹,其中包含从个人的地址和电话号码到其Facebook的“喜欢”和在线购物偏好的所有内容。
NoSQL的最常见类型:
-
键值存储 Key-Value Stores:数据存储在键值对数组中。“键”是链接到“值”的属性名称。著名的键值存储包括Redis,Voldemort和Dynamo。
-
文档数据库 Document Databases:在这些数据库中,数据存储在文档中(而不是表中的行和列),并且这些文档在集合中分组在一起。每个文档可以具有完全不同的结构。文档数据库包括CouchDB和MongoDB。
-
宽列数据库 Wide-Column Databases:在列数据库中,我们有列族,而不是“表”,列族是行的容器。与关系数据库不同,我们不需要预先知道所有列,并且每一行不必具有相同的列数。列式数据库最适合分析大型数据集-大型名称包括Cassandra和HBase。
-
图形数据库 Graph Databases:这些数据库用于存储关系最好用图形表示的数据。数据保存在具有节点(实体),属性(有关实体的信息)和线(实体之间的连接)的图形结构中。图数据库的示例包括Neo4J和InfiniteGraph。
SQL和NoSQL之间的高级别差异
存储: SQL将数据存储在表中,其中每一行代表一个实体,每一列代表有关该实体的数据点;例如,如果我们将汽车实体存储在表中,则不同的列可以是“颜色”,“制造”,“模型”等。
NoSQL数据库具有不同的数据存储模型。主要的是键值,文档,图形和柱状。我们将在下面讨论这些数据库之间的差异。
模式:在SQL中,每条记录都遵循固定的模式,这意味着必须在输入数据之前确定和选择列,并且每一行必须具有每一列的数据。该模式可以在以后进行更改,但是它涉及到修改整个数据库并使其脱机。
在NoSQL中,模式是动态的。可以动态添加列,每个“行”(或等效行)不必包含每个“列”的数据。
查询: SQL数据库使用SQL(结构化查询语言)来定义和处理数据,这非常强大。在NoSQL数据库中,查询集中于文档集合。有时也称为UnQL(非结构化查询语言)。不同的数据库使用UnQL的语法不同。
可伸缩性:在大多数情况下,SQL数据库是垂直可伸缩的,即通过增加硬件的能力(更高的内存,CPU等),这会变得非常昂贵。可以在多个服务器之间扩展关系数据库,但这是一个挑战性且耗时的过程。
另一方面,NoSQL数据库是水平可伸缩的,这意味着我们可以在NoSQL数据库基础结构中轻松添加更多服务器以处理大量流量。任何廉价的商品硬件或云实例都可以托管NoSQL数据库,从而使其比垂直扩展更具成本效益。许多NoSQL技术还可以在服务器之间自动分配数据。。任何廉价的商品硬件或云实例都可以托管NoSQL数据库,从而比垂直扩展更具成本效益。许多NoSQL技术还可以在服务器之间自动分配数据。
可靠性或ACID兼容性(原子性,一致性,隔离性,耐久性):绝大多数关系数据库都符合ACID。因此,在数据可靠性和执行事务的安全保证方面,SQL数据库仍然是更好的选择。
SQL VS NoSQL 使用哪个
使用SQL
- 我们需要确保符合ACID。通过严格规定事务与数据库的交互方式,ACID合规性可减少异常并保护数据库的完整性。通常,NoSQL数据库牺牲了ACID的可伸缩性和处理速度,但是对于许多电子商务和金融应用程序而言,ACID兼容的数据库仍然是首选。
- 您的数据是结构化且不变的。如果您的企业没有经历需要大量服务器的大规模增长,并且仅使用一致的数据,则可能没有理由使用旨在支持各种数据类型和高流量的系统。
使用NoSQL
当我们应用程序的所有其他组件快速且无缝地运行时,NoSQL数据库可防止数据成为瓶颈。大数据为NoSQL数据库取得了巨大成功,主要是因为它处理数据的方式不同于传统的关系数据库。NoSQL数据库的一些流行示例是MongoDB,CouchDB,Cassandra和HBase。
- 存储通常很少甚至没有结构的大量数据。NoSQL数据库对我们可以存储在一起的数据类型没有任何限制,并允许我们根据需求的变化添加新的类型。使用基于文档的数据库,您可以将数据存储在一个地方,而不必事先定义数据的“类型”。
- 充分利用云计算和存储。基于云的存储是一种出色的节省成本的解决方案,但需要将数据轻松分布在多台服务器上以进行扩展。在现场或在云中使用商品(价格合理的,较小的)硬件可以为您节省其他软件的麻烦,而像Cassandra这样的NoSQL数据库则旨在跨多个数据中心进行扩展,而不会造成很多麻烦。
- 快速开发。NoSQL对于快速开发非常有用,因为它不需要提前准备。如果您正在进行系统的快速迭代,而这需要对数据结构进行频繁的更新,而各版本之间不会造成大量停机,那么关系数据库将使您的运行速度变慢。
CAP Theorem
CAP定理指出,分布式软件系统不可能同时提供以下三个保证(CAP)中的三个以上:一致性,可用性和分区容限。在设计分布式系统时,在CAP之间进行权衡几乎是我们要考虑的第一件事。CAP定理说,在设计分布式系统时,我们只能从以下三个选项中选择两个:
一致性 Consistency:所有节点同时看到相同的数据。通过在允许进一步读取之前更新几个节点来实现一致性。
可用性 Availability:每个请求都会获得成功/失败的响应。通过跨不同服务器复制数据来实现可用性。
分区容限 Partition tolerance:尽管消息丢失或部分失败,系统仍可继续工作。容忍分区的系统可以承受任何数量的网络故障,而这不会导致整个网络的故障。可以在节点和网络的组合之间充分复制数据,以通过间歇性中断来保持系统正常运行。
我们无法建立一个通用的数据存储,该数据存储可以连续使用,顺序一致并且可以容忍任何分区故障。我们只能构建具有这三个属性中的任何两个属性的系统。因为要保持一致,所有节点都应以相同的顺序看到相同的更新集。但是,如果网络丢失了一个分区,则在客户端从最新分区读取后,该分区中的更新可能不会使其更新到其他分区。应对这种可能性的唯一办法是停止服务来自过期分区的请求,但随后该服务不再100%可用。
一致性哈希 Consistent Hashing
Why
分布式哈希表(DHT)是分布式可伸缩系统中使用的基本组件之一。哈希表需要一个键,一个值和一个哈希函数,其中哈希函数将键映射到存储值的位置。
索引= hash_function(键)
假设我们正在设计一个分布式缓存系统。给定“ n”个缓存服务器,直观的哈希函数将是“键%n”。它很简单并且经常使用。但是它有两个主要缺点:
- 它不是水平可伸缩的。每当将新的缓存主机添加到系统时,所有现有映射都将被破坏。如果缓存系统包含大量数据,将是维护方面的一个痛点。实际上,很难安排停机时间来更新所有缓存映射。
- 它可能无法实现负载平衡,尤其是对于非均匀分布的数据。实际上,可以很容易地假设数据将不会均匀分布。对于高速缓存系统,它转换为某些高速缓存变得饱和,饱和,而其他高速缓存变为空闲且几乎为空。
在这种情况下,一致的哈希是改善缓存系统的好方法。
What 什么是一致性哈希?
对于分布式缓存系统和DHT分布式哈希表,一致性哈希是一种非常有用的策略。它使我们能够以在添加或删除节点时最大程度地减少重组的方式在整个群集中分布数据。因此,缓存系统将更容易按比例放大或缩小。
在“一致性哈希”中,当调整哈希表的大小(例如,将新的缓存主机添加到系统中)时,仅需要重新映射“ k / n”个键,其中“ k”是键的总数,而“ n”是键服务器总数。回想一下,在使用“ mod”作为哈希函数的缓存系统中,所有键都需要重新映射。
在“一致性哈希”中,如果可能,对象将映射到同一主机。从系统中删除主机后,该主机上的对象将由其他主机共享;因此,主机上的对象将被共享。添加新主机后,它将从几个主机中获取其共享,而不会影响其他人的共享。
How 它是如何工作的?
作为典型的哈希函数,一致哈希将键映射到整数。假设哈希函数的输出在[0,256]范围内。想象一下,将范围内的整数放置在环上,以便将值包裹起来。
一致性哈希的工作方式如下:
- 给定缓存服务器列表,将它们哈希为该范围内的整数。
- 要将密钥映射到服务器,
- 将其哈希为单个整数。
- 在环上顺时针移动,直到找到它遇到的第一个缓存。
- 该缓存是包含密钥的缓存。例如:key1映射到缓存A;key2映射到缓存C。
要添加一个新服务器(例如D),原来位于C的密钥将被拆分。其中一些将移至D,而其他键将不会被触碰。
要删除缓存,或者如果缓存失败,例如说A,则所有最初映射到A的键都将落入B,而只有那些键需要移到B;其他键不会受到影响。
如前所述,对于负载平衡,实际数据基本上是随机分布的,因此可能不一致。这可能会使高速缓存上的密钥不平衡。
为了解决此问题,我们为缓存添加了“虚拟副本”。我们没有将每个缓存映射到环上的单个点,而是将其映射到环上的多个点,即副本。这样,每个高速缓存与环的多个部分相关联。
如果哈希函数“很好地混合”,则随着副本数量的增加,密钥将更加平衡。
长轮询与WebSocket与服务器发送的事件 Long-Polling vs WebSockets vs Server-Sent Events
- Ajax轮询
- HTTP长轮询
- Web套接字
- 服务器发送的事件(SSE)
长轮询,WebSocket和服务器发送事件是客户端(如Web浏览器和Web服务器)之间流行的通信协议。首先,让我们开始了解标准HTTP Web请求的外观。以下是常规HTTP请求的一系列事件:
- 客户端打开连接并向服务器请求数据。
- 服务器计算响应。
- 服务器根据打开的请求将响应发送回客户端。
Ajax轮询
轮询是绝大多数AJAX应用程序使用的一种标准技术。基本思想是客户端反复轮询(或请求)服务器以获取数据。客户端发出请求,并等待服务器响应数据。如果没有可用数据,则返回空响应。
- 客户端使用常规HTTP打开连接并从服务器请求数据。
- 所请求的网页以规则的时间间隔(例如0.5秒)将请求发送到服务器。
- 服务器计算响应并将其发送回,就像常规HTTP流量一样。
- 客户端定期重复上述三个步骤,以从服务器获取更新。
- 轮询的问题在于,客户端必须不断向服务器询问任何新数据。结果,许多响应为空,从而造成HTTP开销。
HTTP长轮询
这是传统轮询技术的一种变体,该技术允许服务器在数据可用时将信息推送到客户端。使用Long-Polling,客户端可以像正常轮询中一样完全从服务器请求信息,但是期望服务器可能不会立即响应。这就是为什么这种技术有时被称为“悬挂式GET”的原因。
- 如果服务器没有可供客户端使用的任何数据,则服务器将保留请求并等待直到一些数据可用为止,而不是发送空响应。
- 一旦数据可用,完整的响应将发送到客户端。然后,客户端立即从服务器重新请求信息,以使服务器几乎总是具有可用的等待请求,服务器可以使用该请求来响应事件。
使用HTTP Long-Polling的应用程序的基本生命周期如下:
- 客户端使用常规HTTP发出初始请求,然后等待响应。 服务器延迟其响应,直到有可用的更新或发生超时为止。
- 当有可用的更新时,服务器会将完整的响应发送到客户端。
- 客户端通常会在收到响应后立即发送新的长轮询请求,或者在允许允许的等待时间段的暂停后发送新的长轮询请求。
- 每个长轮询请求都有一个超时。由于超时而关闭连接后,客户端必须定期重新连接。
Web套接字
WebSocket提供全双工单个TCP连接上的通信通道。它在客户端和服务器之间提供了持久的连接,双方都可以使用该连接随时开始发送数据。客户端通过称为WebSocket握手的过程建立WebSocket连接。如果该过程成功,则服务器和客户端可以随时在两个方向上交换数据。WebSocket协议使客户端和服务器之间的通信具有较低的开销,从而促进了服务器之间的实时数据传输。通过提供一种标准化的方法,使服务器无需客户端询问即可将内容发送到浏览器,并允许在保持连接打开的情况下来回传递消息. 通过这种方式,客户端和服务器之间可以进行双向(双向)正在进行的对话。
分类 | 定义 | 例子 |
---|---|---|
半双工(half-duplex) | 允许二台设备之间的双向资料传输,但不能同时进行。因此同一时间只允许一设备发送资料,若另一设备要发送资料,需等原来发送资料的设备发送完成后再处理。 | 无线对讲机 |
全双工(full-duplex) | 允许二台设备间同时进行双向资料传输。全双工的系统可以用复线铁路类比。两个方向的车辆因使用不同的轨道,因此不会互相影响。 | 一般的电话、手机就是全双工的系统,因为在讲话时同时也可以听到对方的声音 |
服务器发送的事件(SSE)
在SSE下,客户端与服务器建立持久的长期连接。服务器使用此连接将数据发送到客户端。如果客户端要向服务器发送数据,则需要使用另一种技术/协议。
客户端使用常规HTTP向服务器请求数据。
所请求的网页将打开与服务器的连接。
只要有新信息可用,服务器就会将数据发送到客户端。
当我们需要从服务器到客户端的实时流量,或者服务器正在循环生成数据并将向客户端发送多个事件时,SSE最好。