课程学习笔记
分析型数据库,即数据仓库的发展经历了几个阶段。上世纪 80 年代,第一代分析型数据库采用的就是传统交易型数据库的共享存储(Share Storage)架构,比如 Oracle 和 IBM Db2,这种架构的缺点是基于专有高端存储,价格昂贵,可扩展性差,扩展到十几个节点往往就会撞到存储的瓶颈。第二代分析型数据库称为 MPP,采用无共享架构(Share Nothing),最早商业化的 MPP 产品为 1980s 出现的 Teradata。Teradata 当时基于大型机和专有硬件。在 2000 年左右出现了几个基于普通 x86 服务器的 MPP 数据仓库公司,比如 Greenplum,Vertica 和 Netezza。基于 x86 的 MPP 架构解决了专有硬件的问题,可扩展性也得到了一定的提高,一般可以扩展到百节点规模。2000 年后,第三代数据仓库 SQL-on-Hadoop,包括 Hive 和 SparkSQL 等,一般都采取了存储与计算分离架构。正是因为存储与计算分离,计算可以访问存储在任何节点的数据,计算才可以在任意节点进行调度,从而可以实现高可扩展性,比如可以扩展到几千节点。存储与计算分离的另外一个好处是管理的简单性,比如扩容不再需要像 MPP 一样重新分布所有数据。管理上的简单性使得存储与计算分离特别适合云的环境。但是一般 SQL-on-Hadoop 兼容性不佳,性能一般,对 Update/Delete 以及混合工作负载支持的也不好。新一代云数据仓库,融合了 MPP 和 Hadoop 的两者的优点,在兼容性和性能等方面补足了以往产品的短板,整体表现更优秀。OushuDB 从设计之初就定位在新一代云数据仓库,其新一代 SIMD 执行器比传统 MPP 要快 5-10 倍,比一般的 SQL-on-Hadoop 要快 20 倍左右。OushuDB 支持 Update/Delete 和混合工作负载,实现了自研存储、对象存储,突破了 HDFS 的瓶颈。在可扩展性方面,采取了存储与计算分离的架构,可以扩展到上万节点,并且可以原生适应云计算的弹性需求。OushuDB 的架构图,分为客户端、主节点、虚拟计算集群、虚拟存储集群四个主要部分。OushuDB 5.0 重磅推出了多主节点架构,增加了虚拟存储集群以及虚拟计算实例,在计算和存储层面全都做到了虚拟化,更好的应对未来不断更新的计算和存储需求。从架构出发,OushuDB 具有非常多的特点和优势。存储与计算分离架构,多个主节点处理用户对数据库的连接请求 (JDBC/ODBC),处理用户认证及协调分布式执行计划引擎、数千个计算/存储节点分布式调度服务来完成后续 SQL 查询的处理流程,分布式执行计划引擎 ,负责用户端标准 SQL 语句的解析、语意检查、基于代价的查询优化到最终产生分布式的查询任务规划工作,分布式任务调度引擎 QD ,负责执行计划的分发与执行状态跟踪,同时也负责节点间的数据分发,支持 SIMD 的极速执行引擎,负责将分布式调度引擎转发的逻辑计划转换成物理计划并完成资源配置,启动并控制整个查询计划的 执行并将执行结果透过分布式调度引擎传回上层执行节点,分布式可插拔存储引擎 ,提供支持 HDFS/S3/本地表存储等多种存储引擎及数据格式(行存、列存)数据的编码、压缩、存储与读写等机制,分布式事务管理,提供全局的数据库读写 ACID 机制,支持分布式锁, 支持并发读写能力,数据库元数据管理,提供数据对象管理与存储,支持基于 MVCC 的事务处理机制,全局资源管理,提供支持多租户的基于多级资源队列的全局任务资源统一分配。OushuDB 是一个分布式系统,那么它需要 Master 的节点和 Segment 节点。Master 节点主要负责接收和处理用户的查询,并将其分解成不同的任务,分派给不同的 Segment 节点。不同的 Segment 节点接收到 Master 分派的任务后,会 fork 成不同的 QueryExecutor 进程协同完成任务。之后将结果返回给 Master 节点,最终由 Master 节点返回给 Client。为保证高可用服务,Master 还配置了 standby 节点。这样,当 Master 节点出现故障时,standby 节点会接管成为新的 Master 节点,从而进一步保证集群的可用性。这就是一个普通的计算过程,那么 OushuDB 是计算和存储分离的。它的数据是存储 Magma 或者是 HDFS 上,Magma 是 OushuDB 从 4.0 引入的。高性能,高可用的分布式存储系统,在主节点上需要配置 MagmaObserver 他用来提供整个集群的 Magma 可用节点,在各个从节点上会配置 MagmaNode。用来提供访问和存储 Magma 数据的服务,那数据还可以放在 HDFS 上。这样,我们这样需要配置 HDFS 服务,在主节点上,我们需要配置 NameNode。在各个子节点上需要配置 DataNode,从而提供对于 HDFS 数据的访问。除此之外,OushuDB 既支持 Standalone 和 Yarn 模式,那 Standalone 说 OushuDB 作为一个独立的应用独占系统资源。同时,他还支持 Yarn,也就是说,OushuDB 作为一个单独的应用程序注册的 Yarn。由 Yarn 进行整个的集群的资源管理和分配,在这时候,我们需要配置 Yarn 服务。在主节点上,我们需要配置 ResourceManager,在各个子节点上需要配置 Node Manager。得到了从上图所示在上面的部分提供了些 Master 节点的服务。在下图中,独立的节点各个的 Segment 节点,他们之间通过高速的 Internect 进行连接。我们选取了 4 个节点和 20 个节点两种不同情况来讲解具体的部署。我们使用缺省的 Standalone 的配置,也就是 OushuDB 将独占整个系统资源。在 4 个节点的配置情况,由于节点数比较少,每节点都要充当 Segment 节点,我们可以看到,上面的两个节点既充当 Master 节点又要充当 Segment 节点。我们首先来看 OushuDB 的 Master,我们需要 Master 和 standby 两个机器来协同工作,同步元数据信息,从而提供 OushuDB 集群的高可用性。MagmaObserver 会分别跟随 OushuDBMagma 和 OushuDB Standby。当 Master 和 standby 发生切换时,同样的,MagmaObserver 也切换到 Standby 节点上。针对 HDFS 我们也提供了 HA 服务,那为了保证负载均衡,我们通常会将 HDFS 的 Active NameNode 和 OushuDB 的 Master 配在两个不同的机器上。我们刚才讲到 ZookeeperNode 推荐配置三个节点,那在本例中,我们选择其中三个机器作为 Zookeeper Node。通常来讲,所有的 Zookeeper 中要有 2 个尽量选择在 Master 节点上,这些节点就承担了 Master 节点的角色。对于 Segment,我们需要 OushuDBSegment,MagmaSegment 以及 DataNode,我们可以看到每个机器上都有这样的进程,进而提供 Segment 的角色。我们再来看 20 个节点的部署。在这种情况下,由于节点数比较多,那么我们可以选择一些节点仅作为 Segment 的角色,选择其中 2 个节点作为进行 Master 配置,其中一个作为 OushuDBMaster 另一个 OushuDBStandby。同理,Magma 的 Observer 也分别部署在不同的机器上。我们选择了 3 个节点的 Zookeeper 搭建了 ZookeeperNode,进而保证 HDFS 的 HA。同样,我们配置了不同的 active NameNode 和 Standby。此前讲授不同的是,我们不需要在 Master 节点同时配置 Segment,因为 20 节点是比较多的。我们可以看到,所有的 Master 节点上没有 Segment 节点,我们选取了其中的(n-2)个,也就是 18 个机器配置所有的 Segment,其中有一个节点还有 ZookeeperNode。那当集群进一步扩容到更多节点的时候,我们可以将后续的 Segment 角色同样复制,那么在更大的集群上会有更多的节点来充当 Segment 的角色。那当集群非常多的时候,我们依然同样也可以将 HDFS 的 NameNode 拆成独立的节点进行部署。尽管 OushuDB 同时提供了 Magma 和 HDFS,如果想单独使用 Magma,也可以不部署 HDFS,HDFS 的 NameNode 服务、DataNode 服务以及所有的 Zookeeper 都不需要了。OushuDB 的 Segment、Magma 和 Data Node 的部署基本一致,这样主要是为了保证本地读。虽然 OushuDB 支持外部的 HDFS,但是这样的话会走网络,影响性能。因此,我们推荐将他们部署在同一个机器上,这样的话,查询计划也会尽量选择读取本地数据,从而实现本地读。当然,我们可以支持外部的 HDFS,尤其当多个集训共享数据的时候,可以通过建立外部表直接访问数据。首先先看 PostMaster 进程,他监听用户请求的守护进程,为每个客户端 fork 连接出单独的 postgres 服务,当 postgres 进程出错时尝试修复;当 Segment 节点的 postgres 挂掉时候会认为节点已经 down 掉了。
Logger 进程负责收集各个进程的输出并将其写入 pg_log,这里包括成功 log 和出错的 log。Stats collector 进程会统计收集数据的信息,会生成描述数据库、表等统计信息的。stat 文件。Writer 进程是定期将共享内存的数据写到磁盘上的进程。再看下面一对进程 Master resource manager 和 Segment resource manager。Masterresource manager 负责管理、分配、回收资源,定期查询、接收、处理 Segment 的心跳信息,从而获取整个集群可用的节点;Segment resource manager 是查询本节点的状态,包括查询临时文件是否可读写,发送 Segment 的心跳信息。下面的进程是 Master 节点上独有的,首先我们来看 DFS metadata cache,由于 OushuDB 是存储和计算分离的,数据存储在 HDFS 或 magma 上,DFS metadata cache 读取并缓存 block location 信息,从而计算数据的存储,也就是存储数据的这些 block 是如何分布的,因此在生成查询计划时,可以确定去某些节点访问某些数据的速度,从而进一步保证本地读。Checkpoint 负责周期性做 checkpoint 或响应常规的 checkpoint 请求。Sequence 是产生序列,也我们通常说的自增长列。下面两个进程是保证 Master 的节点和 Standby 节点元数据信息进行同步的。Wal send server 进程负责把 write ahead log 发给 StandbyMaster,而 Sync agent 负责和 Master 上 wal send server 通信的进程,处理 Master 和 standby 节点状态。