暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

Citus实现PostgreSQL数据库的分布式架构

呆呆的私房菜 2024-09-18
400
    Whoami:5年+金融、政府、医疗领域工作经验的DBA
    Certificate:OCP、PCP
    Skill:Oracle、Mysql、PostgreSQL
    Platform:CSDN、墨天伦、公众号(呆呆的私房菜)
    复制


    阅读本文可以了解基于citus扩展来实现PostgreSQL数据库的分布式架构相关内容,包含citus的架构描述、集群设计、常见问题及搭建部署案例等。


    01

    Citus概述
    • citus是一个开源的PostgreSQL扩展程序,旨在将原生的PostgreSQL数据库转换成一个分布式数据库;

    • Citus能显著提升数据库处理大规模数据集的能力,尤其在需要进行复杂查询和高并发的场景下表现突出;

    • citus不仅保留了PostgreSQL的强大功能特性,如事务处理、ACID特性等,并且还增加了分布式计算所需的场景,例如数据分区、负载均衡和故障恢复机制。

    • citus节点设计:

    • 1. cn协调节点:负责接收客户端的交互请求,并生成分布式执行计划;本地维护元数据,如分片信息,节点存储位置等;

    • 2. wn数据节点:实际的计算和存储节点,支持水平扩展。


    • citus表类型设计:

    • 分区表:数据根据分片算法分布于多个工作节点上,适用于大表,频繁更新的表;

    • 参考表:数据集中在一个分片上,该分片在每个工作节点上复制;适用于需要和分片表join的表,主要针对小表、恨少更新的表;

    • 本地表:本地存储的表,适用于对小表的高并发复杂查询场景。

    • citus分片表设计:

    分片类型分片特征
    适用场景
    hash分片采用一致性哈希原理,[-2^32,2^32-1]平均分成n个区间,通过对分片字段key取值hash_int32(key)计算具体所属区间。是使用较多的分片方式;
    常见于多租户场景、查询多围绕某列的场景,对多租户应用一般选择租户id作为分片键进行分区。
    range分片分片大小增加到一定量自动创建新的分片,需人工指定每个分片范围。Range分片使用较少。

    分片键选择:

    1.  where、join出现频率高的列;

    2.  高基数且值分布均匀的字段;

    3.  日期(按天)通常不适合作为分片字段,业务往往倾向于访问最近的数据,容易形成热点;


    02

    Citus集群设计
    • 原生citus不支持HA,不像mongodb一样具备故障自动修复能力,但是可以结合pg和流复制来实现读写分离和故障切换。

    • 1. 提升读能力

    • 配置多个cn节点,节点之间使用流复制方式进行同步,以此保持元数据一致。在应用层面设置多个读写分离,保证数据的一致性,同时保证业务的高可用。

    • 2. citus mx特性

    • citus mx特性允许应用程序直接连接到工作节点进行行数据的读取和写入,从而增加集群的并发数量,这种模式类似于拥有多个协调节点的架构,有利于提高查询吞吐量,尤其是在执行大量小的读写操作时。

    • 在citus mx模式下,分布式表的元数据存储在系统表中,当工作节点拥有这些元数据后,便可以提供数据的读取和写入服务。

    • 这个特性很大程度上解决了读写的问题。

    • 3. 流复制实现异地容灾

    • 协调节点和工作节点都通过物理流复制的方式去实现;

    • local dns解析为对应本地机房的主机ip。


    03

    Citus常见问题
    • 分布式数据库解决了单机数据库的数据量、吞吐、并发、计算效率等问题,但数据分布方式的变化会带来新的问题,包括数据热点问题、数据倾斜问题、分布式扩展能力等;

    • 当然,数据热点、数据倾斜及分布式线性扩展这些问题,可以通过数据迁移的方式进行处理。


    • 分片迁移:分片方式相同的表形成一个分片组进行迁移,原理是迁移一个分片里的所有表,然后修改元数据。

    • citus分片迁移有两个方案:

    • 1. copy table + 修改集群元数据表:这种方式将源表的数据以二进制的方式写入目标表,速度很快,但是需要停业务,适合离线使用;

    • 2. 逻辑订阅 + 修改集群元数据表:这种方式迁移时先全量迁移,再增量迁移,割接时迁移的表只读;这种方案支持在线使用,对业务影响小。


    • 针对上边提到的citus容易出现的问题,解决方案如下:

    • 1. 针对数据热点、数据倾斜的问题,我们可以通过将倾斜的热点数据进行拆分,然后迁移到资源相对宽裕的节点上。

    • 2. 随着业务的增长,数据量越来越大,我们可以通过增加更多的协调节点和工作节点来提升分布式数据库的能力。协调节点必须由主节点才可以修改元数据信息;增加工作节点以为着要进行数据迁移。

    • citus提供了两种算法用于数据迁移,即by_shard_count和by_disk_size,by_shard_count算法会尽可能让每个工作节点的分片数量相同;by_disk_size会进行可能让每个工作节点上的数据量相同。


    04

    Citus 1CN + 2DN搭建案例
    • 环境说明:

    类型主机名
    IP地址
    端口
    CN节点
    pg01
    192.168.56.115432
    WN节点1
    pg02192.168.56.225432
    WN节点2
    pg03192.168.56.335432
      # 如无特殊说明,下列命令所有节点都执行
      1. 主机环境配置
      cat >> etc/sysctl.conf <<-EOF
      kernel.shmmax = 4294967296
      kernel.shmall = 2097152
      kernel.shmmni = 4096
      kernel.sem = 250 32000 100 128
      fs.aio-max-nr = 1048576
      net.ipv4.ip_local_port_range = 9000 65500
      net.core.rmem_default = 262144
      net.core.rmem_max = 4194304
      net.core.wmem_default = 262144
      net.core.wmem_max = 4194304
      fs.file-max = 6815744
      EOF


      2. 配置主机资源限制
      cat >> etc/security/limits.conf <<-EOF
      * soft nofile 1024000
      * hard nofile 1024000
      * soft nproc unlimited
      * hard nproc unlimited
      * soft core unlimited
      * hard core unlimited
      * soft memlock unlimited
      * hard memlock unlimited
      EOF


      3. 安装系统依赖
      yum install apr apr-util bash bzip2 curl krb5 libxml2 libyaml openldap openssh openssl openssl-libs perl rsync R sed tar zip unzip ntp lz4* gcc* libcurl* libevent* flex* bison* readline* zlib* 


      4. 安装zstd
      tar xzf zstd-1.4.4.tar.gz -C usr/local/
      cd /usr/local/zstd-1.4.4
      make -j && make install 


      5. 源码安装PostgreSQL数据库和citus扩展(所有主机执行)
      -- 创建安装用户
      useradd postgres
      echo "postgres#2024" | passwd --stdin postgres
      -- 配置用户环境变量
      cat >> home/postgres/.bash_profile <<-EOF
      export PGHOME=/pg/pg11
      export PGDATA=/pg/pg11/data
      export PATH=\$PATH:\$PGHOME/bin
      export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/zstd-1.4.4/lib/
      EOF
      chown postgres.postgres ~/.bash_profile
      -- 上传postgresql-11.18.tar.gz安装包到/pg/pg11下
      cd /pg/pg11/
      tar xzf postgresql-11.18.tar.gz
      cd postgresql-11.18
      ./configure --prefix=/pg/pg11 --enable-nls --with-perl --with-python --with-tcl --with-gssapi --with-openssl --with-pam --with-ldap --with-libxml --with-libxslt
      make -j 4 && make install
      -- 上传citus-11.3.0.tar.gz 安装包到 pg/pg11/postgresql-11.18/contrib下
      cd /pg/pg11/postgresql-11.18/contrib
      tar xzf citus-11.3.0.tar.gz
      cd citus-11.3.0
      ./configure && make && make install


      6. 初始化主库
      initdb -E UTF8 --locale=en_US.utf8 -U postgres


      7. 主库配置
      -- 修改数据库参数配置
      cat >> $PGDATA/postgresql.conf <<EOF
      listen_addresses = '*'
      port=5432
      unix_socket_directories='/pg/pg11/data'
      logging_collector = on
      log_directory = 'pg_log'
      log_filename = 'postgresql-%a.log'
      log_truncate_on_rotation = on
      wal_level='replica'
      archive_mode='on'
      archive_command='test ! -f /pg/pg11/archive/%f && cp %p /pg/pg11/archive/%f'
      hot_standby=on
      max_wal_senders=10
      wal_sender_timeout=60s
      wal_keep_segments = 128
      max_replication_slots=10
      wal_log_hints=on
      shared_preload_libraries ='citus'
      EOF
      -- 修改访问白名单配置
      cat >> $PGDATA/pg_hba.conf <<EOF
      host    all      all             0.0.0.0/0               md5
      host    all             all             192.168.56.11/24        trust
      host    all             all             192.168.56.22/24        md5
      host    all             all             192.168.56.33/24        md5
      EOF


      8. 启动数据库并创建扩展
      pg_ctl start
      create extension citus;


      9. 配置CN和DN关系(在CN节点执行即可)
      select * from master_add_node('192.168.56.22', 5432);
      select * from master_add_node('192.168.56.33', 5432);
      select * from master_get_active_worker_nodes();


      10. 创建分布式表测试
      create table shard_test(gid serial primary key, tracktime timestamp without time zone);
      select create_distributed_table('shard_test', 'gid');
      insert into shard_test(tracktime) select now()::timestamp(0) + (interval '1 second' * (random() * 86400)) * generate_series(1, 1000);


      11. 查看分片信息
      select * from pg_dist_placement where shardid in (select shardid from pg_dist_shard where logicalrelid='shard_test'::regclass);
      复制


      本文内容就到这啦,阅读完本篇,相信你对Citus实现PostgreSQL分布式架构相关知识有了一定的认识了吧!我们下篇再见!

      点击上方公众号,关注我吧!

      文章转载自呆呆的私房菜,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

      评论