怎么扩展数据库和Nosql数据库——系统设计
一直有记录相关面试相关的资料,慢慢整理放出来
在国外面试公司,大部分公司都需要系统设计相关的经验,很重要一点就是如何从0开始扩展系统从而支撑更大的流量,数据库扩展就是其中重要的一点。
当数据量对于数据库而言太大时,自然会考虑对其进行扩展以应对增加的负载。 但是,根据是SQL还是NoSQL数据库,扩展背后的技术和原理是不同的。 我将探讨两个数据库可扩展性背后的主要思想。 由于本文假定你具有有关数据库及其属性的一些基本知识,因此复习SQL / NoSQL数据库将很有帮助。
垂直和水平扩展
先来理解这两个概念
垂直扩展
垂直扩展是通过增加服务器的硬件容量(例如CPU,RAM)来提高服务器处理能力的过程。 尽管这可能是一个可行的选择,但是硬件改进还有一定的门槛-限制在当前可用的范围内。 另外,在某一点之后,垂直缩放变得太昂贵而不能成为可行的选择。
水平扩展
另一方面,水平扩展可通过增加服务器数量来实现扩展。 从理论上讲,可以根据需要扩展以具有尽可能多的并行服务器,这就是为什么在必须扩展数据库时,水平扩展是的原因。 随着服务器的分发,获得了能够存储更多数据的好处,但是继承了分布式系统的问题。 这里会研究扩展的潜在限制以及如何解决这些限制。
数据库 Sharding
什么是Sharding?
数据库分片的概念是扩展的关键,它适用于SQL和NoSQL数据库。 顾名思义,将数据库分为多个部分(碎片)。 每个分片都有一个与其存储的数据类型相对应的索引。 例如,如果选择按名称索引数据库,则分片A可以存储名称以A–F开头的用户的数据,而分片B可以存储年龄为G–M的用户的数据,依此类推。 当出现搜索查询时,数据库可以快速引用索引并快速查明应该查看的分片,而不是扫描整个数据库。
Sharding的开销
但是,必须注意,数据库分片是有代价的,尤其是对于SQL数据库。 诸如Oracle,MySQL,PostgreSQL之类的整体数据库不支持自动分片,工程师必须手动编写逻辑来处理分片。 通常,由于维护成本高昂,更改架构(例如,如何分片数据库)变得具有挑战性。
扩展数据库
Cluster 代理
假设已经将分片逻辑应用于SQL数据库,你可能会问,查询服务如何知道与哪个分片进行通信以检索数据? 如果你正在考虑一个中间件,那么就走对了。 一种解决方案是将代理(如负载平衡器)放置在查询服务和数据库的前面。 在引擎盖下,负载平衡器依赖于诸如ZooKeeper之类的配置服务来跟踪分片及其索引。 通过处理查询,负载均衡器将确切知道将请求定向到哪个分片。
Shard 代理
到目前为止,通过查看特定的分片而不是扫描整个数据库,在加快查询速度方面做得不错,但是仍然可以做得更好。 与之前所做的类似,可以引入另一个位于负载均衡器和分片之间的代理,将其称为分片代理。 如果分片足够大,可以再次将该代理分片以加快查询速度。 重复分片的过程称为分层分片(hierarchical sharding
)。
除了重定向到特定索引之外,分片代理还可以通过诸如缓存常用数据,监视数据库运行状况,存储和发布有关数据的度量标准以及在请求花费太长时间时终止查询之类的操作来进一步改善查询。
可用性
现在,不再处理单一数据库,所以需要确保当一个实例发生故障时数据仍然可用。 在分布式系统中,确保可用性的解决方案几乎总是引入复制,这样就不会出现单一的故障瓶颈,并且会有可用的备份副本。
回到分片,这里可以使用主从架构来确保可用性。 这个想法是要有一个主分片,它是可读写的,而从分片是只读的,以确保真相的单一来源。 每当进行写操作时,它将直接应用于主分片,然后,主分片会将更改传播到从分片。 可以将读取查询定向到从属分片,以减少主分片的负载。 如果主分片不可用,则分片代理可以选择一个从属分片来替换主分片。
在数据中心级别,可以复制数据库以确保在数据中心发生故障时进行备份。
一致性
SQL数据库在设计时并未考虑可伸缩性,而是考虑了ACID属性(原子性,一致性,隔离性和持久性)。 这样,可以保证SQL数据库的单个实例是一致的。 但是,一旦探索具有SQL数据库的分布式系统并确保数据的可用性,就必然会遇到一致性问题,而这在分布式系统中是不可避免的。
一个简单的比喻是工厂老板在没有扬声器的情况下发布公告。 如果只有几个工作人员,每个人都可以立即收到他的消息。 相反,当有成千上万的工人时,该消息可能需要一段时间才能到达后面的人,因为每个工人都将不得不依靠他们前面的人来传达消息。
回到主从架构,将数据从主服务器传播到从服务器需要一些时间。 因此,存在一个时间窗口,即主机及其从机可以具有不同的状态。 在扩展SQL数据库时,我们为了终的一致性而牺牲了一致性。
扩展Nosql
Cassandra
与SQL数据库相反,NoSQL数据库在设计时考虑了规模。 因此,由于缩放过程是自动完成的,因此终用户在很大程度上看不到缩放过程。 不过,我将简单探索数据库底层发生的事情。 尽管有许多不同类型的NoSQL数据库和不同的扩展方式,但我将使用Cassandra的宽列数据库作为参考。
Shards/Node是平等的
类似于我们对SQL数据库进行分片的方式,NoSQL也具有对应于不同索引的数据库分片。 但是,一个主要区别是,每个分片都是相同的,而不是主从体系结构。 另外,由于涉及图形概念,因此我将碎片称为向前移动的节点,因为这是一个更直观的标签。
节点能够相互通信和交换信息-如果数据本身不包含特定数据,则它们知道该数据存储在何处。 通常,每个节点与之通信的节点数是固定的。 我想这是为了防止O(V²)时间复杂性(其中V是节点数)并将其限制在O(1)时间。
查询进入时,将在集群中选择一个初始协调器节点,以通过算法处理请求。 这样的算法包括轮询或短距离(从请求到节点)。 如果协调器节点没有数据,它将把请求转发到另一个拥有数据的节点,或者知道另一个拥有该数据的节点。
例如,用户F的数据存储在节点A上。节点D(协调节点)可以简单地与节点A通信,并且知道数据存储在节点A上。因此,节点D可以简单地将请求重定向到节点 一个。
同样,当写入请求到达协调器节点时,它将使用一致性hash来确定将数据存储在哪个节点上。
Gossip(传播) 协议
通过节点共享信息的整个想法通常称为Gossip协议,该协议将信息从一个节点传递到另一个节点。 流行病协议是一个替代术语,因为信息的传播与病毒在社区中的传播方式相似。 近的Covid-19大流行应该在理解此协议的效率方面提供一些隐喻!
可用性
如前所述,数据被复制以防止单点故障并保持可用性。 在Cassandra中,由于节点被认为是相等的,因此一个节点可以简单地在其他节点中复制其数据,而无需采用主从结构。 众所周知,当我们拥有分布式系统时,数据复制将异步进行并且需要很长时间。 因此,不必等待所有节点响应协调器节点发出成功复制的信号,协调器节点只需等待x个节点即可响应。 这种等待x个成功写入响应的数量使复制成功的方法称为仲裁写入。
除了在群集级别进行复制外,整个群集的多个副本还存储在不同的数据中心之间,以防止在数据中心级别发生单点故障。
一致性
在大多数NoSQL数据库中,可用性优先于一致性,因为它们具有BASE(基本可用,软状态,终一致)属性。 换句话说,好显示陈旧的数据,而不显示全部数据。 毕竟,正如前面的Gossip协议中所述,节点之间终将具有一致性。 考虑到这些属性,需要高精度数据的金融系统将使用SQL数据库,而较少的“重要”数据(例如视图计数)则可以依赖NoSQL数据库。
当读取查询到达协调器节点,然后协调器节点向复制节点发起并行读取请求时,可能会返回不同的响应。 这种差异可能是由于在复制过程中某些副本节点不可用,或者数据尚未传播到某些节点。 就像我们有定额写入一样,我们也有定额读取,其中返回x个节点同意的响应。
后
希望本文对扩展不同的数据库有所启发。 你现在应该了解,对于分布式数据库,您可能会牺牲某些属性来获得其他属性。 数据复制几乎始终是确保可用性的关键。 使用异步复制,您的数据库起初不会完全一致,但终会完全一致。 和往常一样,我仍在学习这些主题。 如果可以更好地解释任何内容,请随时发表评论或解释。
个人博客 https://patrickchen.cn/
个人公众号:
http://weixin.qq.com/r/ykxMVL-EP_JArfs39xnY (二维码自动识别)
相关文章