ITPub博客

首页 > > > IT系统及PostgreSQL的伸缩(垂直扩展&水平扩展)

IT系统及PostgreSQL的伸缩(垂直扩展&水平扩展)

作者:浪花小雨滴 时间:2020-06-17 16:30:43 0 删除 编辑

分布式系统的垂直扩展和水平扩展

高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。提高系统并发能力的方式,方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)。

垂直扩展:提升单机处理能力。垂直扩展的方式有:

  • 增强单机硬件性能。如:升级CPU算力和核数,升级更好的网卡如万兆,升级更好的硬盘如SSD,扩充硬盘如2T,扩充内存如128G;
  • 提升单机架构性能。如:使用Cache来减少IO次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间;

优点:单机优化易于配置且维护和管理开销最小,性能改善简单快捷;

缺点:增强单机硬件的购置成本高,并且有可能效益不高;单机性能总是有极限的,所以互联网分布式架构设计高并发的终极解决方案还是水平扩展。

水平扩展:通过增加服务器数量,从而线性扩充系统性能。水平扩展对系统架构设计是有要求的。

  • 反向代理层的水平扩展:是通过“DNS轮询”实现的。dns-server对于一个域名配置了多个解析ip,每次DNS解析请求来访问dns-server,会轮询返回这些ip。

当nginx成为瓶颈的时候,只要增加服务器数量,新增nginx服务的部署,增加一个外网ip,就能扩展反向代理层的性能,做到理论上的无限高并发。

  • 站点层的水平扩展:是通过nginx实现的。通过修改nginx.conf,可以设置多个web后端。

当web后端成为瓶颈的时候,只要增加服务器数量,新增web服务的部署,在nginx配置中配置上新的web后端,就能扩展站点层的性能,做到理论上的无限高并发。

  • 服务层的水平扩展:是通过“服务连接池”实现的。

站点层通过RPC-client调用下游的服务层RPC-server时,RPC-client中的连接池会建立与下游服务多个连接,当服务成为瓶颈的时候,只要增加服务器数量,新增服务部署,在RPC-client处建立新的下游服务连接,就能扩展服务层性能,做到理论上的无限高并发。如果需要优雅的进行服务层自动扩容,这里可能需要配置中心里服务自动发现功能的支持。

  • 数据层的水平扩展(缓存、分库、分表)

在数据量很大的情况下,数据层(缓存,数据库)涉及数据的水平扩展,将原本存储在一台服务器上的数据(缓存,数据库)水平拆分到不同服务器上去,以达到扩充系统性能的目的。通常涉及:分布式集群、读写分离、读扩展、写扩展。

数据库作为应用请求的终点,对整体性能的影响很大,以下重点介绍PostgreSQL的水平扩展。

PostgreSQL的垂直扩展和水平扩展

PG垂直扩展方案

单机服务器系统垂直扩展的前提下,还可以对单机数据库性能调优[1]:如:数据库配置调优,使用vacuum进行GC,SQL查询语句AnalyzeExplain并优化,创建索引;

PG水平扩展方案

  • Pgpool II(一主多备,读、写分离,读扩展)

PgPool II 是客户端应用程序和PostgreSQL集群之间的中间件产品。Pgpool II通过负载平衡,将写入发送到主节点,并在备节点之间平衡读取语句,来提供水平可伸缩性。Pgpool II提供连接级别和语句级别的负载平衡;连接级别的负载平衡 Pgpool II 进程与备节点建立连接,该连接的所有读取均发送到备节点,而写入则发送到主节点。使用语句级连接(Pgpool II 4.1中提供),每个语句在备节点上实现负载均衡。

  • 基于PG声明式分区的分片

分片是基于PG声明式分区的。

PG声明式分区:在PG10中首次发布;在声明性分区之前,PG 使用表继承 和 plpgsql 触发器提供表分区。
直接使用声明式分区,可以将位于一个数据服务器上的一个主表拆分出多个子分区;插入主表中的行都将基于分区键被路由到所属分区中。
PG11 对声明性分区的性能进行了许多改进,包括分区修剪。分区修剪:是基于 WHERE 谓词提供的,旨在排除无关分区,将查询直接路由到特定分区。

分片:是一种在一个或多个外部服务器上,对表进行分区的能力。通过声明式分区可以将主表拆分为位于同一数据库服务器上的多个分区表。分片允许对表进行分区,并使分区子表位于外部外部服务器上,而主表位于用户创建分片父表的主节点上。分片表中使用的所有外部服务器都是PostgreSQL外部服务器,不支持其他异构外部服务器,如MongoDB,MySQL等。

--在主服务器上,创建主表
CREATE TABLE measurement (
    city_id         int not null,
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (logdate);

--远程服务器上(shard_1),创建一个分区表(结构与主表相同)
CREATE TABLE measurement_year2019 (
    city_id         int not null,
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) ;

--在主服务器上,给主表绑定外部服务器上的子分区表
CREATE TABLE measurement_year2019 PARTITION OF measurement
       FOR VALUES FROM('2019-01-01') TO ('2020-01-01')
Server shard_1;
  • 基于FDW的内置分片技术

PG内置分片功能使用基于FDW的方法,而FDW基于SQL/ MED规范,该规范定义了如何从PG服务器访问外部数据源。

PG提供了许多用于访问外部数据源的外部数据封装器(FDW):
postgres_fdw 用于访问在外部服务器上运行的Postgres数据库;
oracle_fdw用于从PG访问Oracle数据库;
mysql_fdw 用于从PG访问MySQL数据库;
mongodb_fdw用于访问MongoDB等。


当前存在的一些问题和挑战[2]

1. 用于FDW的两阶段提交
当前,FDW事务不支持两阶段提交,这意味着,如果在一个事务中使用多个外部服务器,并且一部分事务在一台外部服务器中失败,则所有外部事务上的整个事务都将失败。为了保证整个数据库群集中的数据一致性,此功能是必需的。
为了支持OLTP工作负载,此功能是必需的,因此对于分片功能非常重要。
此功能的设计建议和补丁已经发送给hackers 好几年了,但是社区对此没有足够的兴趣,尽管该功能的设计仍然非常出色。
2.并行外部扫描
当一个查询在单个查询中查询多个外部扫描时,所有外部扫描都以一种连续的方式依次执行。并行外部扫描功能正在并行执行多个外部扫描。此功能对于OLAP测试用例确实非常重要,例如,如果您正在对被划分为大量分区的大型分区表上运行AVG查询。AVG操作将顺序发送到每个外部服务器,每个外部服务器的结果将发送到父节点,该父节点将在父节点上聚合并发送回客户端。一旦有了并行foriegn扫描功能,所有外部服务器上的所有平均操作都将并行执行,并将结果发送到父节点。
这是完成分片功能所需的关键部分,我们目前具有聚合下推功能,可以将聚合向下发送到外部服务器,但是我们没有在所有分区上并行运行聚合操作的功能。
对于OLAP用例而言,此功能特别重要,拥有大量外部服务器(包含用于大型分区表的分区)以及在并行运行于所有外部服务器分区上的聚合操作的想法非常大。
并行外部扫描功能的基础结构是异步查询执行,这是PostgreSQL中的一个重大更改。在此方面已经完成了一些工作,但是感觉它仍需一个或两个发行版。一旦异步查询执行完成,添加并行外部扫描功能将变得更加容易。
3. 分片管理
当前不会自动在外部服务器上创建分区,需要在外部服务器上手动创建分区。如果要创建具有大量分区和子分区的分区表,这可能是非常繁琐的任务。
假定分片管理功能提供了在外部服务器上自动创建分区和子分区的功能。这将使分片表的创建非常容易。
不打算讨论如何实现此功能的任何设计细节,其基本思想是,分片表语法将建立在声明性分片语法的基础上。postgres_fdw将用于将DDL下推到外部服务器,而FDW仅用于执行SELECT或DML,而在外部源上执行DDL则不是sql/med规范的一部分。
4. 全局事务管理器/快照管理器
这是分片功能所必需的另一个非常重要且困难的功能。假定全局事务/快照管理器的目的是提供全局事务一致性。本章第1节“用于外部数据包装器事务的2PC”中描述的问题也与全局事务管理器有关。
假设您有两个正在使用分片表的并发客户端,客户端1 试图访问服务器1上的分区,客户端2也试图访问服务器1上的分区。客户端2分区的一致视图,即客户端2不应在客户端1事务中看到对该分区所做的任何更改(即更新等)。客户端2提交事务后,所有新事务都将看到更新。全局事务管理器假设要确保所有全局事务都能获得数据库集群的一致视图。使用数据库群集的所有并发客户端(具有在多个外部服务器上分表的表)应该看到数据库群集的一致视图。
这是很难解决的问题,像Postgres Professional这样的公司已经尝试通过使用外部事务管理器来解决此问题。到目前为止,社区似乎还没有接受任何解决方案。目前,没有明显的集中精力尝试在核心或在外部组件中实现全局事务管理器。
其他方法,例如Clock-SI(分区表的快照隔离)方法,或借鉴其他成功案例(例如谷歌cloud spanner和YugaByte)来解决同一问题。

参考

  1. ^https://www.jdon.com/51929
  2. ^https://mp.weixin.qq.com/s/IAPghS0UqV4Na2_tsCxvVw

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3158789/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-05-16

  • 博文量
    4259
  • 访问量
    39922