PostgreSQL 服务

    单机用户无需关注与接入的概念,这是针对在生产环境中使用高可用PostgreSQL数据库集群所提出的概念。

    完成单机部署后,该节点的5432端口对外提供PostgreSQL数据库服务,80端口对外提供UI类服务。

    在当前元节点上,使用管理用户无参数执行 可以直接连接到本机预定义的 meta 数据库,开箱即用。

    从外部(宿主机)使用客户端工具访问PG时,可以使用以下URL:

    您可以使用由 pg_admin_username 与 指定的管理员用户,或预先在meta数据库中定义的其他业务用户(dbuser_meta)访问该数据库。

    在生产环境使用Pigsty部署的高可用数据库集群,强烈不建议使用IP直连的方式接入数据库服务

    **服务(Service)**是数据库集群对外提供功能的形式。

    在真实世界的生产环境中,我们会使用基于复制的主从数据库集群。集群中有且仅有一个实例作为领导者(主库),可以接受写入,而其他实例(从库)则会从持续从集群领导者获取变更日志,与领导者保持一致。同时从库还可以承载只读请求,对于读多写少的场景可以显著分担主库负载,因此区分集群的写入请求与只读请求是一个常规实践。

    此外对于高频短连接的生产环境,我们还会通过连接池中间件(Pgbouncer)对请求进行池化,减少连接与后端进程的创建开销。但对于ETL与变更执行等场景,我们又需要绕过连接池,直接访问数据库。

    此外,高可用集群在故障时会出现故障切换(Failover),故障切换会导致集群的领导者出现变更。因此高可用的数据库方案要求写入流量可以自动适配集群的领导者变化。

    这些不同的访问需求(读写分离,池化与直连,故障切换自动适配)最终抽象为服务的概念。

    通常来说,数据库集群必须提供一种服务

    • 读写服务(primary) :可以写入数据库

    对于生产数据库集群至少应当提供两种服务

    • 读写服务(primary) :可以写入数据库
    • 只读服务(replica) :可以访问只读数据副本

    此外,根据具体的业务场景,可能还会有其他的服务,例如:

    • 离线从库服务(offline):不承接线上只读流量的专用从库,用于ETL与个人查询
    • 延迟从库服务(delayed) : 允许业务访问固定时间间隔之前的旧数据
    • 默认直连服务(default) : 允许(管理)用户绕过连接池直接管理数据库的服务

    Pigsty默认对外提供四种服务:, replica, , offline

    您可以通过配置文件为全局或单个集群定义新的服务

    以默认的元数据库pg-meta为例

    1. psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5433/meta # 生产读写
    2. psql postgres://dbuser_meta:DBUser.Meta@pg-meta:5434/meta # 生产只读
    3. psql postgres://dbuser_dba:DBUser.DBA@pg-meta:5436/meta # 直连主库
    4. psql postgres://dbuser_stats:DBUser.Stats@pg-meta:5438/meta # 直连离线

    下面将详细介绍这四种服务

    Primary服务服务于线上生产读写访问,它将集群的5433端口,映射为 主库连接池(默认6432) 端口。

    在集群中有且仅有一个实例是主库,只有其健康检查为真。

    主库上的高可用组件Patroni针对Primary健康检查返回200,用于确保集群不会出现一个以上的主库实例。

    当集群发生故障切换时,新主库的健康检查为真,老主库的健康检查为假,因此流量将迁移至新主库上。业务方会察觉到约30秒的 Primary服务 不可用时间。

    Replica服务服务于线上生产只读访问,它将集群的5434端口,映射为 从库连接池(默认6432) 端口。

    Replica服务选择集群中的所有实例作为其成员,但只有健康检查/read-only为真者,才能实际承接流量,该健康检查对所有可以承接只读流量的实例(包括主库)返回成功。所以集群中的任何成员都可以承载只读流量。

    但默认情况下,只有从库承载只读请求,Replica服务定义了selector_backup,该选择器将集群的主库作为 备份实例 加入到Replica服务中。只要当Replica服务中所有其他实例,即所有从库宕机时,主库才会开始承接只读流量

    另一个作为备份实例的角色是offline角色,Offline实例通常专用于OLAP/ETL/个人交互式查询,不适合与在线查询混合,因此只有当集群中所有的replica宕机后,offline才会被用于承接只读流量。

    1. # replica service will route {ip|name}:5434 to replica pgbouncer (5434->6432 ro)
    2. - name: replica # service name {{ pg_cluster }}-replica
    3. src_ip: "*"
    4. src_port: 5434
    5. dst_port: pgbouncer
    6. check_url: /read-only # read-only health check. (including primary)
    7. selector_backup: "[? pg_role == `primary` || pg_role == `offline` ]"

    Default服务服务于线上主库直连,它将集群的5436端口,映射为主库Postgres端口(默认5432)。

    Default服务针对交互式的读写访问,包括:执行管理命令,执行DDL变更,连接至主库执行DML,执行CDC。交互式的操作不应当通过连接池访问,因此Default服务将流量直接转发至Postgres,绕过了Pgbouncer。

    Default服务与Primary服务类似,采用相同的配置选项。出于演示目显式填入了默认参数。

    Offline服务用于离线访问与个人查询。它将集群的5438端口,映射为离线实例Postgres端口(默认5432)。

    Offline服务针对交互式的只读访问,包括:ETL,离线大型分析查询,个人用户查询。交互式的操作不应当通过连接池访问,因此Default服务将流量直接转发至离线实例的Postgres,绕过了Pgbouncer。

    离线实例指的是 为 offline 或带有 pg_offline_query 标记的实例。离线实例外的其他其他从库将作为Offline的备份实例,这样当Offline实例宕机时,Offline服务仍然可以从其他从库获取服务。

    1. # offline service will route {ip|name}:5438 to offline postgres (5438->5432 offline)
    2. src_ip: "*"
    3. src_port: 5438
    4. dst_port: postgres
    5. check_url: /replica # offline MUST be a replica
    6. selector: "[? pg_role == `offline` || pg_offline_query ]" # instances with pg_role == 'offline' or instance marked with 'pg_offline_query == true'
    7. selector_backup: "[? pg_role == `replica` && !pg_offline_query]" # replica are used as backup server in offline service

    在以上由 pg_services 配置的默认服务之外,用户可以使用相同的服务定义,在 配置项中为PostgreSQL数据库集群定义额外的服务。

    一个集群都可以定义多个服务,每个服务包含任意数量的集群成员,服务通过端口进行区分。以下代码定义了一个新的服务standby,使用5435端口对外提供同步读取功能。该服务会从集群中的同步从库(或主库)进行读取,从而确保所有读取都不存在延迟。

    必选项目

    • 名称(service.name

      服务名称,服务的完整名称以数据库集群名为前缀,以service.name为后缀,通过-连接。例如在pg-test集群中name=primary的服务,其完整服务名称为pg-test-primary

    • 端口(service.port

      在Pigsty中,服务默认采用NodePort的形式对外暴露,因此暴露端口为必选项。但如果使用外部负载均衡服务接入方案,您也可以通过其他的方式区分服务。

    • 选择器指定了服务的实例成员,采用JMESPath的形式,从所有集群实例成员中筛选变量。默认的选择器会选取所有的集群成员。

    可选项目

    • 备份选择器(service.selector

      可选的 备份选择器service.selector_backup会选择或标记用于服务备份的实例列表,即集群中所有其他成员失效时,备份实例才接管服务。例如可以将primary实例加入replica服务的备选集中,当所有从库失效后主库依然可以承载集群的只读流量。

    • 源端IP(service.src_ip

      表示服务对外使用的IP地址,默认为*,即本机所有IP地址。使用vip则会使用vip_address变量取值,或者也可以填入网卡支持的特定IP地址。

    • 宿端口(service.dst_port

      服务的流量将指向目标实例上的哪个端口?postgres 会指向数据库监听的端口,pgbouncer会指向连接池所监听的端口,也可以填入固定的端口号。

    • 健康检查方式(service.check_method:

      服务如何检查实例的健康状态?目前仅支持HTTP

    • 健康检查端口(service.check_port:

      服务检查实例的哪个端口获取实例的健康状态? patroni会从Patroni(默认8008)获取,pg_exporter会从PG Exporter(默认9630)获取,用户也可以填入自定义的端口号。

    • 健康检查路径(service.check_url:

      服务执行HTTP检查时,使用的URL PATH。默认会使用/作为健康检查,PG Exporter与Patroni提供了多样的健康检查方式,可以用于主从流量区分。例如,/primary仅会对主库返回成功,/replica仅会对从库返回成功。/read-only则会对任何支持只读的实例(包括主库)返回成功。

    • Haproxy特定配置(service.haproxy

      关于服务供应软件(HAProxy)的专有配置项

    目前Pigsty默认使用基于HAProxy的服务实现,也有基于DPVS 4层负载均衡(L4VIP)的私有实现。两者相互等效,各有优势。详情请参考一节。