当数据库遇到分布式,你会怎么做?
分区的数量通常在数据库第一次建立时确定,之后不会改变。每个分区包含了总数据量固定比率的数据,因此每个分区的大小与集群中的数据总量成比例增长。如果数据集的总大小难以预估,选择正确的分区数是困难的。分区太大,再平衡和节点故障恢复变得昂贵;分区太小,则会产生太多的开销。 动态数量的分区 对于使用键范围进行分区的数据库,具有固定边界的固定数量的分区将非常不方便:如果出现边界错误,则可能会导致某些分区的没有数据。按键范围进行分区的数据库通常会动态创建分区。 当分区增长到超过配置的大小时,会被拆分成两个分区,每个分区约占一半的数据。动态分区的优点是分区数量适应总数据量,能够平衡各方面的开销。HBase和MongoDB采用的就是这种策略。 数据集开始时很小,直到达到第一个分区的分隔点,所有写入操作都必须由单个节点处理,而其他节点处于空闲状态。为了解决这个问题,HBase和MongoDB允许在一个空的数据库上配置一组初始分区(预分隔,pre-splitting)。在键范围分区的情况下,预分隔需要提前知道键时如何分配的。 按照节点比例分区 分区数与节点数量成正比,即每个节点具有固定数量的分区。每个分区的大小与数据集大小成比例的增长。当增加节点时,随机选择固定数量的现有分区进行拆分,然后占有这些拆分分区中的每个分区的一半。 请求路由 现在我们已经数据集分割到多个节点上运行的多个分片上,客户端发起请求时,如何知道连接哪个结点。随着分区再平衡,分区对节点的分配也发生变化。 不仅限于数据库,这个问题可以概括为服务发现(service discovery),通常有以下三种方案: 允许客户端连接任何节点,如果该节点恰巧拥有请求的分区,则直接处理该请求;否则将请求转发到适当的节点,接收结果并返回给客户端。 客户端发送请求到路由层,它决定了应该处理请求的节点,并相应的转发。 客户端知道分区和节点的分配,直接连接到适当的节点。 以上问题的关键在于:做出路由决策的组件如何了解分区-节点之间的分配关系变化?这是一个具有挑战性的问题,因为需要所有的参与者达成一致。 很多分布式系统都依赖于一个独立的协调服务,比如ZooKeeper来跟踪集群元数据。 每个节点在ZooKeeper上注册自己,ZooKeeper维护分区到节点的可靠映射 路由层可以在ZooKeeper订阅此信息,当分区分配发生变化能实时感知 复制 复制意味着在通过网络连接的多台机器上保留相同数据的副本,复制数据能带来以下的好处: 提高可用性,即使系统的一部分出现故障,系统也能继续工作 扩展可以接受读请求的机器数量,从而提高读取吞吐量 使得数据与用户再地理上接近,从而减少延迟 复制的困难之处在于处理复制数据的变更。目前流行有三种变更复制算法:单领导者(single leader),多领导(multi leader)和无领导者(leaderless),几乎所有的分布式数据库都使用这三种方法之一。 单领导者复制过程: 每一次向数据库的写入操作都需要传播到所有的副本上,否则副本就会包含不一样的数据。最常见的解决方案被称为基于领导者的复制 或 主从复制 副本之一被指定为领导者(或主库),当客户端要向数据库写入时,它必须发给领导者,领导者会将新数据写入其本地存储; 其他副本被称为追随者(只读副本、从库),会同步主库的变更日志,按照主库相同的顺序写入 当客户端从数据库读取数据时,可以向领导者或追随者查询 同步 or 异步 (编辑:威海站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |