Linux入门攻坚——69、分布式系统及大型网站架构初步

Source

分布式系统
  1、系统的各组件分布于网路上多个计算机;
  2、各组件彼此之间仅仅通过消息传递来通信并协调行动;
在用户眼中,一个分布式系统中,一组独立的计算机展现给用户的是一个统一的整体,就好像是一个系统似的。

分布式系统存在意义:
  1、向上扩展的性价比越来越低;
  2、单机扩展存在性能上升临界点;
  3、出于稳定性及可用性考虑,单机会存在多方面的问题;

分布式系统拥有多种通用的物理和逻辑资源,如CPU、内存、IO等,分散的物理和逻辑资源通过计算机网络通过消息传递实现信息交换,资源可能是多份的,如CPU就可能是多颗多核CPU,这使得编程难度增加,如实现多CPU并行运行的多线程编程等;

多CPU
  多线程编程:
    互不通信的线程模型
    基于共享容器协同工作的模型
    通过事件协调的多线程模型
        事件A, B
            A:触发事件 
                B:等待事件 
  线程模型又分为:线程安全的模型和线程不安全的模型,不安全的模型一般要使用锁技术解决这种不安全。
  COW:Copy-On-Write,写时拷贝/写时复制,通过延迟实际数据拷贝操作,仅在数据发生写入修改时进行复制操作。该机制可有效减少不必要的内存复制开销,提升系统资源利用率。     
  多进程模型:

网络IO
  多进程,每个进程响应一个请求;
  多线程,多进程,每进程生成多个线程,每线程响应一个用户请求
  多线程,每线程直接响应多个请求

  基于socket实现网络通信开发,其实现方式:
      BIO:Blocking IO
          一个进程或一个线程处理一个请求;
      NIO:Nonblocking IO
          基于事件驱动(epoll)思想,采用Reactor模式
      AIO:Asynchronous IO
          基于事件驱动思想,采用Proactor模式

如何把应用从单机扩展至多机?
  输入设备的变化:
  输出设备的变化:
  控制器的变化:实现的模式    
    透明代理
        lvs的nat
        haproxy,nginx
    旁路代理
    名称服务
    规则服务
    Master/slave机制
  运算器的变化:可以理解为CPU,单一运算器 --> 多运算器
  存储器的变化:

分布式系统实现的难点:
    缺乏全局时钟
    面对故障时的独立性
    处理单点故障
    事务处理
        ACID(原子性Atomicity、一致性Consistency、隔离性Isolation、持久性Durability)    
        2PC、BASE、CAP、Paxos

大型网站站点的架构演进方式(分布式系统在其中的应用):

初始网站:LAMT, LNMT

应用从资源占用的角度分两类:
    CPU Bound:CPU密集型(计算密集型)
    IO Bound: IO密集型(访问密集型)

当M(数据库)压力过大时,要对M进行扩展,如读写分离、负载均衡等;随着访问量增加,应用服务器压力过大,即T(tomcat,java)压力过大,需要对应用做负载均衡,增加主机,此时需要解决会话保持的问题,一般解决方案:
   session sticky: ip based与cookie based
   session replication:
   session server:

当数据库压力持续增加时,可能引入数据库的主从复制架构分担压力,引入主从面临的问题:
  1、数据复制的问题
  2、应用选择数据源的问题
对于客户端对内容的查询,则可能需要引入搜索技术,加入搜索引擎,将全站内容进行索引处理,当客户端再次查询时,将使用搜索引擎进行搜索,压力从数据库给到搜索引擎上,实现数据端的压力分散。

对于站点静态内容,访问量很大时,需要引入缓存,加快响应速度,减轻IO:
  1、页面缓存
        varnish, squid
  2、数据缓存
        key-value store: memcached

数据库写操作增大,主库写操作压力解决方案:数据库拆分
    垂直拆分:把数据库中不同的业务的数据拆分到不同的数据库服务器中
    水平拆分:把一个单独的表中的数据拆分到多个不同的数据库服务器上

数据除了关系型数据,还有非关系型数据和非结构化数据;
NoSQL:非关系型数据
  文档数据库
  列式数据库
    ... ...

DFS(Distributed FS):非结构化数据
  TFS(Taobao FS), MogileFS: 适用于海量小文件
  HDFS(Hadoop Distributed FS), GFS(Google FS):少量大文件

CDN(Content Delivery Network,内容分发网络)技术:分布于全球的边缘服务器节点构成的分布式网络架构,旨在通过就近获取缓存内容提升互联网内容传输效率,解决网络拥塞问题。其核心原理是通过智能DNS解析和负载均衡技术将用户请求导向最优节点,减少数据传输距离与延迟,降低源站负载,也是一种分布式系统。

站点规模再扩大,有时需要对应用拆分:
  根据业务特性拆分:如用户、商品、交易
  根据用户拆分:
      用户注册
      用户登录
      用户信息维护
  根据对底层应用的调用进行拆分:

对于大型网站,对特定的功能进行服务化,形成一些特定的服务,上层应用直接通过调用接口访问这些服务完成应用功能。对接口的调用也可能因压力过大形成瓶颈,可在前端增加队列服务等分散压力,异步执行,进行接口调用的解耦。
  异步:解耦
      消息中间件:在分布式系统中,完成消息发送和接收的基础性软件;
          MOM:Message-Oriented Middleware
          RabbitMQ, ActiveMQ, ZMQ

数据访问层问题:为解决写操作压力的拆分
    拆分:
        垂直拆分:
            单机的ACID保证被打破:要么放弃事务,要么引入分布式事务;
            一些Join查询操作将变得非常困难:
            原来依赖于外键实现的约束将无从保证;
        水平拆分:
            单机ACID保证被打破;
            一些Join查询操作将变得非常困难:
            原来依赖于外键实现的约束将无从保证;
            自增序列的ID号的产生会有影响;
            针对单张表的查询很有可能要跨库操作;

分布式事务的实现
      事务:事务参与者、支持事务的服务器、资源服务器、事务管理器等一般分布于不同节点;
      分布式事务的模型及规范:
          X/Open:XA(分布式事务规范),XA是DTP的一部分接口规范。
              X/Open DTPDistributed Transaction Processing):DTP是一种实现分布式事务处理系统的概念模型,OSI和Open/X组织都有正式文档来定义,它定义了三个组件
                  AP: 应用程序,即使用DTP模型的程序
                  RM:资源管理器,即DBMS系统
                  TM:事务管理器,负责协调和管理管理条例,提供给AP应用程序编程接口并管理资源管理器

应用程序(Application Program,AP):    这个角色要做两件事情,
       一方面是定义构成整个事务所需要的所有操作(就是图中的2,通过TX接口定义事务边界)
      另一方面是亲自访问资源节点来执行操作(就是图中的1)。
资源管理器(Resource Managers,RM):    这个角色是管理着某些共享资源的自治域,比如说一个MySQL数据库实例。在DTP里面,还有两个要求,
    一是RM自身必须是支持事务的,
    二是RM能够根据将全局(分布式)事务标识定位到自己内部的对应事务。
事务管理器(Transaction Manager,TM):    这个角色能与AP和RM直接通信,协调AP和RM来实现分布式事务的完整性。主要的工作是
(1)、提供AP注册全局事务的接口
(2)、颁发全局事务标识(GTID之类 的)
(3)、存储/管理全局事务的内容
(4)、决策并指挥RM做commit/rollback

XA是RM和TM的交互规范和接口定义,XA 就是 X/Open DTP 定义的交易中间件与数据库之间的接口规范(即接口函数),交易中间件用它来通知数据库事务的开始、结束以及提交、回滚等。 XA 接口函数由数据库厂商提供,大部分数据库都提供了XA接口实现。

eXtended Architecture(XA),TM和RM们之间使用的是二阶段提交。

在XA规范的描述中,两阶段提交TM协调RM们完成已定义的全局事务的方法,AP找TM申请/注册全局事务的动作并不是二阶段提交的保障内容。
二阶段提交(two-phase commit,2PC):
对于单个全局(分布式)事务,在DTP环境中,二阶段提交流程大致如下:
    第一阶段(Phase 1)
    TM请求所有RM进行准备(prepare commit, or prepare),并告知它们各自需要做的局部事务(transaction branche)。
    RM收到请求后,如果判断可以完成自己的局部事务,那就持久化局部事务的工作内容,再给TM肯定答复;要是发生了其他情况,那给TM的都是否定答复。在发送了否定答复并回滚了局部事务之后,RM才能丢弃持久化了的局部事务信息。
    第二阶段(Phase 2)
    TM根据情况(比如说所有RM都prepare成功,或者,AP通知它要rollback等),先持久化它对这个全局事务的处理决定和所涉及的RM清单,然后通知所有涉及的RM去提交(commit)或者回滚(rollback)它们的局部事务。
    RM们处理完自己的局部事务后,将返回值告诉TM之后,TM才可以清除掉包括刚才持久化的处理决定和RM清单在内的这个全局事务的信息。

    CAP:2000年7月,Eric Brewer;CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。
      一致性:Consistency,任何一个读操作总是能够读取之前完成的写操作;
      可用性:Availability,每一次操作总是能够在确定的时间返回;
      网络分区容错性:Partition tolerance,出现网络分区情况下,仍能满足一致性和可用性;
一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本);
可用性(A):保证每个请求不管成功或者失败都有响应。;
分区容忍性(P):系统中任意信息的丢失或失败不会影响系统的继续运作。
CAP原则的精髓就是要么AP,要么CP,要么AC,但是不存在CAP。如果在某个分布式系统中数据无副本, 那么系统必然满足强一致性条件, 因为只有独一数据,不会出现数据不一致的情况,此时C和P两要素具备,但是如果系统发生了网络分区状况或者宕机,必然导致某些数据不可以访问,此时可用性条件就不能被满足,即在此情况下获得了CP系统,但是CAP不可同时满足 。

        CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。任何一种分布式系统最多只能同时满足上述三项中的两项;因此,分布式系统的目标:
          AP:放弃C;大多数分布式系统都选择此项;
          CA:放弃P; 单机上一般是CA;
          CP:

CA(一致性和可用性):    在优先考虑一致性和可用性的系统中,尽量避免分区。这种设计选择为强一致性和高可用性而牺牲了分区容忍性。传统的关系型数据库通常属于这一类别。
CP(一致性和分区容忍性):    优先考虑一致性和分区容忍性的系统在网络分区时牺牲了可用性。它们确保数据在所有节点之间保持一致,即使在网络分区期间一些节点暂时不可用。
AP(可用性和分区容忍性):    优先考虑可用性和分区容忍性的系统致力于在存在网络分区的情况下对读和写请求进行响应。然而,这可能导致最终一致性,即所有节点最终将趋于相同的状态,但不一定是立即的。
为什么CAP不能同时实现?
CAP 定理之所以指出在分布式系统中最多只能同时实现三个属性中的两个,是基于分布式环境下的现实限制和权衡考虑。下面解释为什么不能同时实现三个属性:
1.网络分区的存在(Partition Tolerance):    在分布式系统中,节点之间的网络通信可能会发生故障,导致节点之间无法直接通信,形成网络分区。由于网络的不确定性,我们无法保证在任何时刻所有节点都能相互通信。
2.牺牲之一:    当存在网络分区时,CAP 定理要求在保证一致性和可用性中选择一项进行牺牲。如果系统选择保证一致性,那么在网络分区期间可能会牺牲可用性;反之亦然。这是因为在无法进行节点间通信时,要么选择等待所有节点就绪以保证一致性,要么允许某些节点响应请求以保证可用性。
3.不同的应用需求:    不同的应用对一致性、可用性和分区容忍性的需求各不相同。某些应用可能更注重数据的一致性,而另一些应用可能更注重可用性。因此,CAP 定理提供了在设计分布式系统时需要权衡的指导原则,以根据具体需求选择适当的系统特性。
4.权衡的必然性:    CAP 定理强调了在分布式系统中的权衡,因为在网络分区的情况下,同时实现强一致性和完全可用性是困难的。权衡的必然性是基于实际系统设计中的复杂性和挑战,而不是纯粹的理论断言。

  分布式系统的目标:加强A和P,在C上进行妥协;
  BASE模型:  BASE是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的简写。
        BA:Basically Availibale
        S:Soft state: 接受一段时间内的状态不同步;
        E:Eventually Consistent: 最终一致性;

BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。

分布式存储或分布式文件系统
存储分为:
  集中式:
    共享存储:
      NAS:
      SAN:
  分布式存储:
      专用的元数据节点:集中元数据存储;
        数据节点只负责存储数据
      无专用元数据节点:所有节点均完整存储元数据;
        存储了部分数据

分布式存储的挑战:
  节点间通信、数据存储、数据空间平衡、容错、文件系统支持

对于分布式:
  文件系统:有文件系统接口;可以通过挂载操作,挂载到文件系统中;
  存储:不是文件系统,不遵循POSIX规范,无文件系统接口,通过API访问,即无法挂载;

分布式文件系统常见的实现:
  GFS:Google File System --> MapReduce --> BigTable
  HDFS:Hadoop Distributed File System --> MapReduce --> HBase
  上述使用场景:数据不太多的大文件;
  TFS:Taobao File System,将元数据存储于关系型数据库或其他高性能存储中,从而能维护海量文件元数据,即海量小文件场景;
  GlusterFS:去中心化设计;没有中心元数据节点;
  Ceph:Linux内核级实现的分布式文件系统,而且已经被收录进内核;
  MooseFS:mfs,轻量级
  MogileFS:轻量级,perl语言开发。
    FastDFS:参照MogileFS用C语言开发的分布式文件存储系统。

分布式文件系统基本是从google的GFS开始的,google公司发布三篇论文,第一篇是Google文件系统(GoogleFS或GFS),是谷歌公司于2003年设计的可扩展分布式文件系统,用于支持大规模数据密集型应用。其核心架构采用单主节点管理元数据,多台块服务器存储数据,文件被分割为64MB的块并默认复制3份以提高可靠性,目标是在廉价硬件集群上实现高容错性与高吞吐量。系统接口方面,GFS提供了一个相似地文件系统界面,虽然它没有向POSIX那样实现标准的API。文件在目录中按层次组织起来并由路径名标识。体系结构上,一个GFS集群由一个master和大量的chunkserver构成,并被许多客户(Client)访问。Master和chunkserver通常是运行用户层服务进程的Linux机器。只要资源和可靠性允许,chunkserver和client可以运行在同一个机器上。
文件被分成固定大小的块。每个块由一个不变的、全局唯一的64位的chunk-handle标识,chunk-handle是在块创建时由master分配的。ChunkServer将块当作Linux文件存储在本地磁盘并可以读和写由chunk-handle和位区间指定的数据。出于可靠性考虑,每一个块被复制到多个chunkserver上。默认情况下,保存3个副本,但这可以由用户指定。
Master维护文件系统所以的元数据(metadata),包括名字空间、访问控制信息、从文件到块的映射以及块的当前位置。它也控制系统范围的活动,如块租约(lease)管理,孤儿块的垃圾收集,chunkserver间的块迁移。Master定期通过HeartBeat消息与每一个chunkserver通信,给chunkserver传递指令并收集它的状态。与每个应用相联的GFS客户代码实现了文件系统的API并与master和chunkserver通信以代表应用程序读和写数据。客户与master的交换只限于对元数据(metadata)的操作,所有数据方面的通信都直接和chunkserver联系。客户和chunkserver都不缓存文件数据。但用户缓存元数据(metadata)。Chunkserver也不必缓存文件,因为块时作为本地文件存储的。

第二篇是mapreduce,是由Google公司研究提出的一种面向大规模数据处理的并行计算模型和方法。Google公司设计MapReduce的初衷主要是为了解决其搜索引擎中大规模网页数据的并行化处理。Google公司发明了MapReduce之后首先用其重新改写了其搜索引擎中的Web文档索引处理系统。由于MapReduce可以普遍应用于很多大规模数据的计算问题,因此自发明MapReduce以后,Google公司内部进一步将其广泛应用于很多大规模数据处理问题。MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算。概念"Map(映射)"和"Reduce(归约)",是它们的主要思想,都是从函数式编程语言里借来的,还有从矢量编程语言里借来的特性。它极大的方便了编程人员在不会分布式并行编程的情况下,将自己的程序运行在分布式系统上。 当前的软件实现是指定一个Map(映射)函数,用来把一组键值对映射成一组新的键值对,指定并发的Reduce(归约)函数,用来保证所有映射的键值对中的每一个共享相同的键组。

第三篇是BigTable,为解决海量数据存储的问题,Google的软件开发工程师研发了Bigtable,是Google为其内部海量的结构化数据开发的云存储技术,是 NoSQL 数据库的先驱之一,核心特性包括:
    ‌- 分布式与可扩展‌:BigTable 设计用于部署在上千台普通服务器上,能够处理 PB 级别的数据,并支持动态伸缩,通过增加节点来线性提升读写吞吐量。
    ‌- 高性能与低延迟‌:专为高并发、低延迟的读写操作优化,适用于实时分析、用户画像、物联网时序数据等场景。
   - 稀疏、多维的键值映射‌:其数据模型本质上是一个稀疏的、分布式的、持久化的多维排序映射(Map),键由‌行键(Row Key)‌、‌列键(Column Key)‌ 和‌时间戳(Timestamp)‌ 三级构成,值为任意字节串。

    ‌- 列族(Column Family)管理‌:列被组织成列族,列族是访问控制和存储压缩的基本单元。同一列族的数据物理上存储在一起,且列族在表创建时定义,列(Qualifier)可动态增减。
    ‌- 多版本支持‌:每个单元格(Cell)可以保存多个版本的数据,通过时间戳区分,默认按时间戳降序存储,便于获取最新数据,同时支持自动版本回收策略。
    ‌- 依赖底层基础设施‌:构建在 Google 的分布式文件系统 ‌Colossus‌(GFS 的后继者)之上,数据以 ‌SSTable‌ 格式持久化存储,并依赖 ‌Chubby‌ 服务进行分布式锁和元数据协调。
BigTable 系统主要由三个核心组件构成:
    ‌- 客户端库(Client Library)‌:为应用程序提供 API 接口,并缓存元数据(如 Tablet 位置信息),客户端直接与 Tablet 服务器通信,不经过主服务器。
    ‌- 主服务器(Master Server)‌:负责元数据管理、Tablet 分配与负载均衡、Tablet 服务器监控以及模式变更(如创建表)。它不直接参与数据读写,是系统的协调者。
    ‌- Tablet 服务器(Tablet Server)‌:实际存储和处理数据的节点。每个 Tablet 服务器管理多个 Tablet(一个 Tablet 是一个行范围的子表,通常 100-200MB),负责处理客户端的读写请求,并在 Tablet 过大时自动分裂。

hadoop公司参考google公司的思想,开发了HDFS、MapReduce和HBase。

分布式文件系统设计目标:访问透明 、位置透明、并发透明、失效透明、硬件透明 、 可扩展性、 复制透明 、 迁移透明;