文章目录
- 分布式理论
- CAP定理
- BASE理论
- 分布式存储与一致性哈希
- 简单哈希
- 一致性哈希
- 虚拟节点
分布式理论
CAP定理
- 一致性(Consistency): 在分布式系统中的所有数据副本,在同一时刻是否一致(所有节点访问同一份最新的数据副本)。
- 可用性(Availability): 分布式系统在面对各种异常时可以提供正常服务的能力(非故障的节点在有限的时间内返回合理的响应)。
- 分区容错性(Partition Tolerance): 分布式系统在遇到任何网络分区故障的时候,仍然需要能对外提供一致性和可用性的服务,除非是整个网络环境都发生了故障。
一个分布式系统不可能同时满足一致性、可用性、分区容错性这三个基本需求,最多只能满足其中的两项,不可能三者兼顾。
为什么三者不可兼顾呢?
这跟 网络分区 这一概念有关:在分布式系统中,不同的节点分布在不同的子网络(机房或异地网络等)中,由于一些特殊的原因导致这些子网络之间出现网络不连通的状况(但各个子网络的内部网络是连通的),从而导致了整个系统的网络环境被切分成了若干个孤立的区域。
此时,每个区域内部可以通信,但是区域之间无法通信。
对于一个分布式系统而言,组件必然要被部署到不同的节点上,因此必然会出现子网络。我们无法保证网络始终可靠,那么网络分区则是必定会产生的异常情况。当发生网络分区的时候,如果我们要继续提供服务,那么 分区容错性P 是必定要满足的。
那么一致性C和可用性A可以兼顾吗?
答案是否定的。倘若分布式系统中出现了网络分区的情况,假设此时某一个节点在进行写操作,为了保证一致性,那么就必须要禁止其他节点的读写操作以防止数据冲突,而此时就导致其他的节点无法正常工作,即与可用性发生冲突。而如果让其他节点都正常进行读写操作的话,那就无法保证数据的一致,影响了数据的一致性。
BASE理论
- 基本可用(Basically Available): 基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性(响应时间上的损失、系统功能上的损失)。但是,这绝不等价于系统不可用。
- 软状态(Soft-state): 允许系统中的数据存在中间状态(数据不一致),并认为该中间状态的存在不会影响系统的整体可用性。即允许系统在不同节点的数据副本之间进行数据同步时存在延时。
- 最终一致性(Eventually Consistent): 最终一致性强调的是系统中所有的数据副本最终能够达到一致,而不需要实时保证系统数据的强一致性。
BASE理论
是基本可用 、软状态和最终一致性 三个短语的缩写。是对 CAP
中的一致性和可用性权衡后的结果。
总的来说,BASE理论
面向的是大型高可用可扩展的分布式系统,它完全不同于 ACID
的强一致性模型,而是提出通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。 但同时,在实际的分布式场景中,ACID特性
与 BASE理论
往往又会结合在一起使用。
分布式存储与一致性哈希
如果我们需要存储QQ号与个人信息,建立起 <QQ号, 个人信息>
的 KV
模型。
假设 QQ
有 10亿
用户,并且每个用户的个人信息占据了 100M
,如果要存储这些数据,所需要的空间就得 (100亿* 100M) = 10WT
,这么庞大的数据是不可能在单机环境下存储的,只能采用分布式的方法,用多个机器进行存储,但是即使使用多机,这些数据也至少要 10w
台机器(假设每台服务器存 1T
)才能存储。那么我们如何确定哪些数据应该放在哪个机器呢?这时就需要用到哈希算法。
简单哈希
我们可以采用除留余数法来完成一个映射:
机器编号 = hash(QQ号) % 机器数量
使用时再根据机器编号进入对应的机器进行增删查改即可。
但是这个方法存在着一个致命的缺陷,如果后续用户信息增加,10w
台机器就会不够用,此时就需要将机器数量扩容至 15w
台。
当进行扩容后,由于机器数量发生变化,数据的映射关系也会变化,我们就需要进行 rehash
来将所有数据重新映射到正确的位置上。
但是问题来了,这 10w
台机器的数据如果需要进行重新映射,花费的时间几乎是不可想象的,我们不可能说为了迁移数据而让服务器宕机数月之久,所以这种方法是不可能行得通的。
一致性哈希
为了弥补简单哈希的缺陷,引入了一致性哈希算法。以避免扩容后 rehash
带来的所有数据迁移问题。一致性哈希将哈希构造成一个 0~232-1 的环形结构,并将余数从原来的机器数量修改值为整型最大值(也可以是比这个更大的):
机器编号 = hash(QQ号) % 2^32
因为这个数据足够大,所以无需担心后续机器数增加导致的 rehash
问题。我们将环中的某一区间映射到某台服务器,让这台服务器管理这个区间,这样就能让这 10w
台服务器来切分这个闭环结构。
哈希环上的数据节点向顺时针方向寻找到的第一个服务器就是管理它的服务器。
当我们要查询某个数据的时候,根据哈希函数算出的映射位置来找到包含该位置的区间所对应的服务器,然后在那个服务器中进行操作即可。
如果原先的服务器不够用了,此时增加 5w
个服务器,也不需要像之前一样对所有机器的数据进行迁移,我们只需要迁移负载重的机器即可。
同理,如果一个服务器宕机了,那么该服务器的上的数据就会被顺时针方向的下一个服务器接管:
但是这样的接管容易引发雪崩,即C节点由于承担了B节点的数据,所以C节点的负载会变高,C节点很容易也宕机,这样依次下去,这样造成整个集群都挂了。
虚拟节点
为此,引入了虚拟节点的概念:即把想象在这个环上有很多虚拟节点,数据的存储是沿着环的顺时针方向找一个虚拟节点,每个虚拟节点都会关联到一个真实节点。
图中的A1、A2、B1、B2、C1、C2、D1、D2都是虚拟节点,机器A负载存储A1、A2的数据,机器B负载存储B1、B2的数据,机器C负载存储C1、C2的数据。由于这些虚拟节点数量很多,均匀分布,因此不会造成“雪崩”现象。
通过虚拟节点,我们可以做到不增加真实的服务器数量即可解决数据分布不均匀。