分布式解决方案概论

分布式解决方案概论

  为了解决单机的容量、性能、高可用等瓶颈问题,各种各样的分布式技术和解决方案不断涌现,分布式文件系统、分布式计算、分布式消息、分布式事务、分布式数据库等等,它们分别别用于解决不同场景的不同问题,本文简单阐述了它们的原理和作用。理解可能不够深入,摘录内容较多,欢迎指正。

一、原理和工具

  • CAP 原则: CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
  • BASE: BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。接下来我们着重对BASE中的三要素进行详细讲解。基本可用:指分布式系统在出现不可预知故障的时候,允许损失部分可用性。
  • PAXOS 算法: Paxos 算法解决的问题是一个分布式系统如何就某个值(决议)达成一致。一个典型的场景是,在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点执行相同的操作序列,那么他们最后能得到一个一致的状态。为保证每个节点执行相同的命令序列,需要在每一条指令上执行一个“一致性算法”以保证每个节点看到的指令一致。一个通用的一致性算法可以应用在许多场景中,是分布式计算中的重要问题。因此从20世纪80年代起对于一致性算法的研究就没有停止过。节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing)。Paxos 算法就是一种基于消息传递模型的一致性算法。
  • Zookeeper 服务: ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper是以Fast Paxos算法为基础的,Paxos 算法存在活锁的问题,即当有多个proposer交错提交时,有可能互相排斥导致没有一个proposer能提交成功,而Fast Paxos做了一些优化,通过选举产生一个leader (领导者),只有leader才能提交proposer。

二、分布式文件系统(HDFS)

 Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。它和现有的分布式文件系统有很多共同点。但同时,它和其他的分布式文件系统的区别也是很明显的。HDFS是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。HDFS放宽了一部分POSIX约束,来实现流式读取文件系统数据的目的。
 HDFS采用master/slave架构。一个HDFS集群是由一个Namenode和一定数目的Datanodes组成。Namenode是一个中心服务器,负责管理文件系统的名字空间(namespace)以及客户端对文件的访问。集群中的Datanode一般是一个节点一个,负责管理它所在节点上的存储。HDFS暴露了文件系统的名字空间,用户能够以文件的形式在上面存储数据。从内部看,一个文件其实被分成一个或多个数据块,这些块存储在一组Datanode上。Namenode执行文件系统的名字空间操作,比如打开、关闭、重命名文件或目录。它也负责确定数据块到具体Datanode节点的映射。Datanode负责处理文件系统客户端的读写请求。在Namenode的统一调度下进行数据块的创建、删除和复制。
在这里插入图片描述
 Namenode和Datanode被设计成可以在普通的商用机器上运行。这些机器一般运行着GNU/Linux操作系统(OS)。HDFS采用Java语言开发,因此任何支持Java的机器都可以部署Namenode或Datanode。由于采用了可移植性极强的Java语言,使得HDFS可以部署到多种类型的机器上。一个典型的部署场景是一台机器上只运行一个Namenode实例,而集群中的其它机器分别运行一个Datanode实例。这种架构并不排斥在一台机器上运行多个Datanode,只不过这样的情况比较少见。
 集群中单一Namenode的结构大大简化了系统的架构。Namenode是所有HDFS元数据的仲裁者和管理者,这样,用户数据永远不会流过Namenode。
参考文档: http://hadoop.apache.org/docs/r1.0.4/cn/hdfs_design.html

三、分布式计算(Map/Reduce)

 Hadoop Map/Reduce是一个使用简易的软件框架,基于它写出来的应用程序能够运行在由上千个商用机器组成的大型集群上,并以一种可靠容错的方式并行处理上T级别的数据集。
 一个Map/Reduce 作业(job) 通常会把输入的数据集切分为若干独立的数据块,由 map任务(task)以完全并行的方式处理它们。框架会对map的输出先进行排序, 然后把结果输入给reduce任务。通常作业的输入和输出都会被存储在文件系统中。 整个框架负责任务的调度和监控,以及重新执行已经失败的任务。
 通常,Map/Reduce框架和分布式文件系统是运行在一组相同的节点上的,也就是说,计算节点和存储节点通常在一起。这种配置允许框架在那些已经存好数据的节点上高效地调度任务,这可以使整个集群的网络带宽被非常高效地利用。
在这里插入图片描述

 Map/Reduce框架由一个单独的master JobTracker 和每个集群节点一个slave TaskTracker共同组成。master负责调度构成一个作业的所有任务,这些任务分布在不同的slave上,master监控它们的执行,重新执行已经失败的任务。而slave仅负责执行由master指派的任务。
 应用程序至少应该指明输入/输出的位置(路径),并通过实现合适的接口或抽象类提供map和reduce函数。再加上其他作业的参数,就构成了作业配置(job configuration)。然后,Hadoop的 job client提交作业(jar包/可执行程序等)和配置信息给JobTracker,后者负责分发这些软件和配置信息给slave、调度任务并监控它们的执行,同时提供状态和诊断信息给job-client。
 虽然Hadoop框架是用JavaTM实现的,但Map/Reduce应用程序则不一定要用 Java来写 。
参考文档:http://hadoop.apache.org/docs/r1.0.4/cn/mapred_tutorial.html

四、分布式数据库(OceanBase)

 OceanBase是由蚂蚁金服、阿里巴巴完全自主研发的分布式关系型数据库,始创于2010年。OceanBase具有数据强一致、高可用、高性能、在线扩展、高度兼容SQL标准和主流关系型数据库、低成本等特点,适用于对性能、成本和扩展性要求高的金融场景。

主要特性:

  • 高性能:OceanBase采用了读写分离的架构,把数据分为基线数据和增量数据。其中增量数据放在内存里(MemTable),基线数据放在SSD盘(SSTable)。对数据的修改都是增量数据,只写内存。所以DML是完全的内存操作,性能非常高。
  • 低成本:OceanBase通过数据编码压缩技术实现高压缩。数据编码是基于数据库关系表中不同字段的值域和类型信息,所产生的一系列的编码方式,它比通用的压缩算法更懂数据,从而能够实现更高的压缩效率。使用PC服务器和低端SSD,高存储压缩率降低存储成本,高性能降低计算成本,多租户混部充分利用系统资源。
  • 高可用:数据采用多副本存储,少数副本故障不影响数据可用性。通过“三地五中心”部署实现城市级故障自动无损容灾。
  • 强一致:数据多副本通过paxos协议同步事务日志,多数派成功事务才能提交。缺省情况下读、写操作都在主副本进行,保证强一致。
  • 可扩展:集群节点全对等,每个节点都具备计算和存储能力,无单点瓶颈。可线性、在线扩展和收缩。
  • 兼容性:兼容常用MySQL/ORACLE功能及MySQL/ORACLE前后台协议,业务零修改或少量修改即可从MySQL/ORACLE迁移至OceanBase。

应用场景:

  • OceanBase的产品定位是一款分布式关系数据库,OceanBase产品适用于金融、证券等涉及交易、支付和账务等对高可用、强一致要求特别高,同时对性能、成本和扩展性有需求的金融属性场景,以及各种关系型结构化存储的OLTP应用。

软件架构:

  • OceanBase设计为一个Share-Nothing的架构,所以它是没有任何的共享存储结构的。至少需要部署三个以上的Zone,数据在每个Zone都存储一份。OceanBase的整个设计里面没有任何的单点,每个Zone有多个ObServer节点,这就从架构上解决了高可靠高可用的问题。
  • 各个节点之间完全对等,各自有各自的SQL引擎和存储引擎。存储引擎只能访问本地数据,而SQL引擎可以访问到全局Schema,并生成分布式的查询计划。查询执行器可以访问各个节点的存储引擎,并在各个节点间做数据的分发和收集,完成分布式计划的执行,并把结果返回给用户。
  • 其中一个节点还会额外担负起RootService服务,RootService同样会有多个备分布在各个Zone。主RootService和所有ObServer之间维持租约,当ObServer出现故障时,主RootService能够检测到并执行故障恢复操作。RootService是ObServer进程的一个功能模块,每台ObServer都具备RootService功能。RootService的功能主要包括:服务器与Zone管理、分区管理、每日合并控制、系统自举、DDL操作等等。
    在这里插入图片描述

五、分布式消息(Kafka)

分布式架构:

  • 每个Broker 代表一个kafka服务器,同时支持多个消息的生产者Producer和多个消息的消费者consumer。
  • 以主题Topic为单位管理消息,每个Topic可以有多个分区partition分别存放在不同的Broker。
  • Kafka 允许 topic 的 partition 拥有若干副本,你可以在server端配置partition 的副本数量。当集群中的节点出现故障时,能自动进行故障转移,保证数据的可用性。
  • Zookeeper用于 kafka 的Broker注册、Topic注册、保存消费者与分区的对应关系、触发消费者的负载均衡、保存消费者的offset。
  • 创建副本的单位是 topic 的 partition ,正常情况下, 每个分区都有一个 leader 和零或多个 followers 。 总的副本数是包含 leader 的总和。 所有的读写操作都由 leader 处理,一般 partition 的数量都比 broker 的数量多的多,各分区的 leader 均 匀的分布在brokers 中。所有的 followers 节点都同步 leader 节点的日志,日志中的消息和偏移量都和 leader 中的一致。(当然, 在任何给定时间, leader 节点的日志末尾时可能有几个消息尚未被备份完成)。Followers 节点就像普通的 consumer 那样从 leader 节点那里拉取消息并保存在自己的日志文件中。Followers 节点可以从 leader 节点那里批量拉取消息日志到自己的日志文件中。
  • 与大多数分布式系统一样,自动处理故障需要精确定义节点 “alive” 的概念。Kafka 判断节点是否存活有两种方式。节点必须可以维护和 ZooKeeper 的连接,Zookeeper 通过心跳机制检查每个节点的连接。如果节点是个 follower ,它必须能及时的同步 leader 的写操作,并且延时不能太久。
    在这里插入图片描述

应用场景:

  • Kafka 作为 Message brokers 可用于各种场合(如将数据生成器与数据处理解耦,缓冲未处理的消息等)。 与其他消息系统相比,Kafka拥有更好的吞吐量、内置分区、具有复制和容错的功能,这使它成为一个非常理想的大型消息处理应用。
  • Kafka 的初始用例是将用户活动跟踪管道重建为一组实时发布-订阅源。 这意味着网站活动(浏览网页、搜索或其他的用户操作)将被发布到中心topic,其中每个活动类型有一个topic。 这些订阅源提供一系列用例,包括实时处理、实时监视、对加载到Hadoop或离线数据仓库系统的数据进行离线处理和报告等。
  • Kafka 可以从外部为分布式系统提供日志提交功能。 日志有助于记录节点和行为间的数据,采用重新同步机制可以从失败节点恢复数据。 Kafka的日志压缩 功能支持这一用法。
  • 数据写入Kafka后被写到磁盘,并且进行备份以便容错。直到完全备份,Kafka才让生产者认为完成写入,即使写入失败Kafka也会确保继续写入Kafka使用磁盘结构,具有很好的扩展性—50kb和50TB的数据在server上表现一致。可以存储大量数据,并且可通过客户端控制它读取数据的位置,您可认为Kafka是一种高性能、低延迟、具备日志存储、备份和传播功能的分布式文件系统。

消息交付语义保证:

  • At most once——消息可能会丢失但绝不重传。
  • At least once——消息可以重传但绝不丢失。
  • Exactly once——这正是人们想要的, 每一条消息只被传递一次。

其他保证:

  • 生产者发送到特定topic partition 的消息将按照发送的顺序处理。 也就是说,如果记录M1和记录M2由相同的生产者发送,并先发送M1记录,那么M1的偏移比M2小,并在日志中较早出现。
  • 一个消费者实例按照日志中的顺序查看记录。
  • 对于具有N个副本的主题,我们最多容忍N-1个服务器故障,从而保证不会丢失任何提交到日志中的记录。

参考文档:https://kafka.apachecn.org/intro.html

六、分布式事务(RocketMQ)

强一致性方案(数据库层面),二阶段提交2PC:

  • 2PC 引入一个事务协调者的角色来协调管理各参与者(也可称之为各本地资源)的提交和回滚,二阶段分别指的是准备(投票)和提交两个阶段。
  • 准备阶段协调者会给各参与者发送准备命令,你可以把准备命令理解成除了提交事务之外啥事都做完了。同步等待所有资源的响应之后就进入第二阶段即提交阶段(注意提交阶段不一定是提交事务,也可能是回滚事务)。
  • 假如在第一阶段所有参与者都返回准备成功,那么协调者则向所有参与者发送提交事务命令,然后等待所有事务都提交成功之后,返回事务执行成功。
  • 假如在第一阶段有一个参与者返回失败,那么协调者就会向所有参与者发送回滚事务的请求,即分布式事务执行失败。
  • 那第二阶段提交失败的话,如果第二阶段执行的是回滚事务操作,那么答案是不断重试,直到所有参与者都回滚了,不然那些在第一阶段准备成功的参与者会一直阻塞着。
  • 那第二阶段提交失败的话,如果第二阶段执行的是提交事务操作,那么答案也是不断重试,因为有可能一些参与者的事务已经提交成功了,这个时候只有一条路,就是头铁往前冲,不断的重试,直到提交成功,到最后真的不行只能人工介入处理。
  • 协调者故障,通过选举得到新协调者。

TCC(Try - Confirm - Cancel):

  • Try 指的是预留,即资源的预留和锁定,注意是预留。
  • Confirm 指的是确认操作,这一步其实就是真正的执行了。
  • Cancel 指的是撤销操作,可以理解为把预留阶段的动作撤销了。
  • 比如说一个事务要执行A、B、C三个操作,那么先对三个操作执行预留动作。如果都预留成功了那么就执行确认操作,如果有一个预留失败那就都执行撤销动作。TCC模型还有个事务管理者的角色,用来记录TCC全局事务状态并提交或者回滚事务。
  • 在业务层面,由于对于每一个操作你都需要定义三个动作分别对应Try - Confirm - Cancel,因此 TCC 对业务的侵入较大和业务紧耦合,需要根据特定的场景和业务逻辑来设计相应的操作。另外,撤销和确认操作的执行可能需要重试,因此还需要保证操作的幂等。
  • 相对于 2PC、3PC ,TCC 适用的范围更大,但是开发量也更大,毕竟都在业务上实现,而且有时候你会发现这三个方法还真不好写。不过也因为是在业务上实现的,所以TCC可以跨数据库、跨不同的业务系统来实现事务。

最终一致性,本地消息表:

  • 这里以支付服务和会计服务为例,大概流程是这样子:用户在支付服务完成了支付订单支付成功后,此时会调用会计服务的接口生成一条原始的会计凭证到数据库中。因为用户完成支付后,此时得立马给用户一个支付的反馈,要做的就是提醒用户支付成功。
  • 本地消息表顾名思义就是会有一张存放本地消息的表,一般都是放在数据库中。然后在执行业务的时候将业务的执行操作(支付服务)和将消息放入消息表中的操作放在同一个事务中,这样就能保证消息放入本地表中业务肯定是执行成功的。
  • 然后再去调用下一个操作(会计服务),如果下一个操作调用成功了好说,消息表的消息状态可以直接改成已成功。
  • 如果调用失败也没事,会有 后台任务定时去读取本地消息表,筛选出还未成功的消息再调用对应的服务,服务更新成功了再变更消息的状态。
  • 这时候有可能消息对应的操作不成功,因此也需要重试,重试就得保证对应服务的方法是幂等的,而且一般重试会有最大次数,超过最大次数可以记录下报警让人工处理。

最终一致性,事务消息(RocketMQ):

  • 事务消息方案可以用来替代本地消息表的方案
  • 第一步先给 Broker 发送事务消息即半消息,半消息不是说一半消息,而是这个消息对消费者来说不可见,然后发送成功后发送方再执行本地事务。再根据本地事务的结果向 Broker 发送 Commit 或者 RollBack 命令。
  • 并且 RocketMQ 的发送方会提供一个反查事务状态接口,如果一段时间内半消息没有收到任何操作请求,那么 Broker 会通过反查接口得知发送方事务是否执行成功,然后执行 Commit 或者 RollBack 命令。
  • 如果是 Commit 那么订阅方就能收到这条消息,然后再做对应的操作,做完了之后再消费这条消息即可。
  • 如果是 RollBack 那么订阅方收不到这条消息,等于事务就没执行过。
  • 可以看到通过 RocketMQ 还是比较容易实现的,RocketMQ 提供了事务消息的功能,我们只需要定义好事务反查接口即可。

参考文档:https://zhuanlan.zhihu.com/p/183753774

猜你喜欢

转载自blog.csdn.net/ManWZD/article/details/115046513
今日推荐