说明:
分布式数据库中的扩容是必不可少的需求,citus企业版中可以进行动态扩容,社区版中尚不支持动态扩容。不过我们可以通过修改元数据表中的分片信息来实现类似的功能。
本次实验扩容前只有一个work节点,扩容成两个work节点。
例子:
我们可以通过citus自带的master_add_node函数来添加节点到集群中,现有的参考表可哟自动分布到新的节点中,但是分片表却不可以自动同步到新的work节点中。
对于分片表,我们则需要手动移动这些分片,大致步骤为:
1、表复制
在移动目标分片的源端和目的端建立复制。
2、元数据切换
加锁,阻塞相关的分片表的数据变更;
修改pg_dist_shard_placement元数据表,变更分片位置信息。
3、清理
DROP切换前的旧的分片。
表复制采用PostgreSQL的逻辑复制实现,因此所有worker节点必须预先打开逻辑复制开关。
wal_level = logical
分片表扩容步骤:
1、创建新的参考表和分片表。
参考表:
citus=# CREATE TABLE t_citus (
citus(# user_id integer NOT NULL,
citus(# name character varying(32)
citus(# );
CREATE TABLE
citus=# SELECT create_reference_table('t_citus');
create_reference_table
------------------------
(1 row)
citus=# insert into t_citus select generate_series(1,100),'bill';
INSERT 0 100
分片表:
citus=# set citus.shard_count = 8;
SET
citus=# create table t1(id int,info text);
CREATE TABLE
citus=# SELECT create_distributed_table('t1', 'id','hash');
create_distributed_table
--------------------------
(1 row)
citus=# insert into t1 select generate_series(1,1000000),md5(random()::text);
INSERT 0 1000000
2、检查分片表位置
可以看到全部在groupid为2这个节点上。
citus=# select * from pg_dist_placement where shardid in (select shardid from pg_dist_shard where logicalrelid='t1'::regclass);
placementid | shardid | shardstate | shardlength | groupid
-------------+---------+------------+-------------+---------
34 | 102041 | 1 | 0 | 2
35 | 102042 | 1 | 0 | 2
36 | 102043 | 1 | 0 | 2
37 | 102044 | 1 | 0 | 2
38 | 102045 | 1 | 0 | 2
39 | 102046 | 1 | 0 | 2
40 | 102047 | 1 | 0 | 2
41 | 102048 | 1 | 0 | 2
(8 rows)
citus=# select * from pg_dist_node;
nodeid | groupid | nodename | nodeport | noderack | hasmetadata | isactive | noderole | nodecluster | metadatasynced
--------+---------+----------+----------+----------+-------------+----------+----------+-------------+----------------
2 | 2 | oracle | 2019 | default | f | t | primary | default | f
(1 row)
3、添加新的work节点
新的work节点groupid为6。
citus=# select * from master_add_node('dmdb04', 1921);
psql: NOTICE: Replicating reference table "t_citus" to the node dmdb04:1921
master_add_node
-----------------
6
(1 row)
citus=# select * from pg_dist_node;
nodeid | groupid | nodename | nodeport | noderack | hasmetadata | isactive | noderole | nodecluster | metadatasynced
--------+---------+----------+----------+----------+-------------+----------+----------+-------------+----------------
2 | 2 | oracle | 2019 | default | f | t | primary | default | f
6 | 6 | dmdb04 | 1921 | default | f | t | primary | default | f
(2 rows)
4、复制分片到新的节点
通过逻辑订阅的方式将原先work节点上的分片同步到新的节点中。
在原先groupid=2的节点创建发布:
bill@citus=>create publication pub_citus for table t1_102041;
CREATE PUBLICATION
在groupid=6的新节点创建订阅:
citus=# create table t1_102041(id int,info text);
CREATE TABLE
citus=# CREATE SUBSCRIPTION sub_citus
CONNECTION 'dbname=citus host=oracle port=2019'
PUBLICATION pub_citus;
psql: NOTICE: created replication slot "sub_citus" on publisher
CREATE SUBSCRIPTION
查看新节点中表数据:
已经同步过来了。
citus=# select count(*) from t1_102041 ;
count
--------
125447
(1 row)
5、切换元数据
可以看到其中一个分片已经在groupid=6的新节点上了。
citus=# update pg_dist_placement set groupid=6 where shardid=102041 and groupid=2;
UPDATE 1
citus=# select * from pg_dist_placement where shardid in (select shardid from pg_dist_shard where logicalrelid='t1'::regclass);
placementid | shardid | shardstate | shardlength | groupid
-------------+---------+------------+-------------+---------
35 | 102042 | 1 | 0 | 2
36 | 102043 | 1 | 0 | 2
37 | 102044 | 1 | 0 | 2
38 | 102045 | 1 | 0 | 2
39 | 102046 | 1 | 0 | 2
40 | 102047 | 1 | 0 | 2
41 | 102048 | 1 | 0 | 2
34 | 102041 | 1 | 0 | 6
(8 rows)
6、清理
groupid=2节点:
bill@citus=>drop publication pub_citus ;
DROP PUBLICATION
bill@citus=>drop table t1_102041;
DROP TABLE
新节点:
citus=# drop subscription sub_citus ;
psql: NOTICE: dropped replication slot "sub_citus" on publisher
DROP SUBSCRIPTION