Citus扩展

Citus是PostgreSQL目前已知水平扩容的插件中最成功的一款, 而且在2019年微软收购了该公司,足以证明该扩展的成功和流行,收购后citus的功能依然保持开源,所以这是一款值得使用并同时值得花时间研究的软件。

多CN节点部署, 数据同步, 不建议在不同的CN对同一个DB进行DDL操作。

由于在开源版本中,没有对多CN部署进行显式支持,现在琢磨出来的办法,虽然支持多点写入,但有如下限制。

  1. 支持同时对不同的数据库进行数据操作,同一个数据库由同一个CN路由进来
  2. 同一个库的数据,不要通过多个CN进行更改,但可以通过多个CN进行查询
  3. CN之间的元数据不会自动同步,需要手工操作,其中最为关键的是 sequence 值的维护

dump表定义

pg_dump -Upostgres -ddemo -s -n 'yourschemaname' > /tmp/schemaname.sql

导入表定义

psql -Upostgres -ddemo -f /tmp/schenaname.sql

同步citus元数据

重要的元数据表

  • pg_dist_partition
  • pg_dist_shard
  • pg_dist_placement
  • pg_dist_node
  • pg_dist_node_metadata
create extension dblink;

insert into pg_dist_partition select * from dblink('host=localhost user=demo dbname=test', 'select * from
 pg_dist_partition') as a(logicalrelid regclass, partmethod char, partkey text, colocationid int, repmodel char) on conflict(logicalrelid) do nothing;

--从另一个CN中导入pg_dist_shard中差异的部分
insert into pg_dist_shard select * from dblink('host=localhost user=demo dbname=test', 'select * from pg_dist_shard') as 
a(logicalrelid regclass, shardid bigint, shardstorage char, shardminvalue text, shardmaxvalue text) on conflict(shardid) do nothing;

insert into pg_dist_placement select * from dblink('host=localhost user=demo dbname=test', 'select * from pg_dist_placement') 
as a(placementid bigint, shareid bigint, shardstate int, shardlength bigint, groupid int) on conflict(placementid) do nothing;

如果只针对某一张表进行元数据同步,可以采用如下步骤

select * from pg_dist_partition where logicalrelid::text like '%tablename%';
select * pg_dist_shard where logicalrelid='tablename'::regclass;
select * from pg_dist_placement where shardid=shardid
select format('alter table %s drop column xxx', table_name) from citus_shards where table_name like 'xxx%' and node_name=xxx;

元数据同步的最后,是设置sequence,在PG中,如果向表中插入记录的时候,已经指定了sequence字段所在的值,那么对应的sequence值不会自动更新,这时需要手工维护。

select setval('pg_catalog.pg_dist_shardid_seq', (SELECT MAX(shardid)+1 AS max_shard_id FROM pg_dist_shard), true);
select  setval('pg_catalog.pg_dist_placement_placementid_seq', (SELECT MAX(placementid)+1 AS max_placement_id FROM pg_dist_placement), true);
select setval('pg_catalog.pg_dist_groupid_seq', (SELECT MAX(groupid)+1 AS max_group_id FROM pg_dist_node), true);
select setval('pg_catalog.pg_dist_node_nodeid_seq', (SELECT MAX(nodeid)+1 AS max_node_id FROM pg_dist_node), true);
select setval('pg_catalog.pg_dist_colocationid_seq', (SELECT MAX(colocationid)+1 AS max_colocation_id FROM pg_dist_colocation), true);

查看某个sequence的当前值, 在pg 11.2之后,可以把sequence看做普通的表进行查询

select *  from pg_dist_shardid_seq;