再談Citus 多CN部署與Citus MX
Citus集群由Coordinator(CN節點)和Worker節點組成。CN節點上放元數據負責SQL分發; Worker節點上放實際的分片,各司其職。
但是,Citus裡它們的功能也可以靈活的轉換。
1. Worker as CN
當一個普通的Worker上存儲了元數據後,就有了CN節點分發SQL的能力,可以分擔CN的負載。
這樣的Worker按官方的說法,叫做Citus MX節點。
配置Citus MX的前提條件為Citus的複製模式必須配置為streaming
。即不支持在多副本的HA部署架構下使用
citus.replication_model = streaming
然後將普通的Worker變成Citus MX節點
select start_metadata_sync_to_node('127.0.0.1',9002);
默認情況下,Citus MX節點上也會分配分片。官方的Citus MX架構中,Citus MX集群中所有Worker都是Citus MX節點。
如果我們只想讓少數幾個Worker節點專門用於分擔CN負載,那麼這些節點上是不需要放分片的。
可以通過設置節點的shouldhaveshards屬性進行控制。
SELECT master_set_node_property('127.0.0.1', 9002, 'shouldhaveshards', false);
2. CN as Worker
Citus裡CN節點也可以作為一個Worker加到集群裡。
SELECT master_add_node('127.0.0.1', 9001, groupid => 0);
CN節點作為Worker後,參考表也會在CN上存一個副本,但默認分片是不會存在上面的。
如果希望分片也在CN上分配,可以把CN的shouldhaveshards屬性設置為true。
SELECT master_set_node_property('127.0.0.1', 9001, 'shouldhaveshards', true);
配置後Citus集群成員如下:
postgres=# select * from pg_dist_node;
nodeid | groupid | nodename | nodeport | noderack | hasmetadata | isactive | noderole | nodecluster | metadatasynced | shouldhaveshards
--------+---------+-----------+----------+----------+-------------+----------+----------+-------------+----------------+------------------
1 | 1 | 127.0.0.1 | 9001 | default | f | t | primary | default | f | t
3 | 0 | 127.0.0.1 | 9000 | default | t | t | primary | default | f | t
2 | 2 | 127.0.0.1 | 9002 | default | t | t | primary | default | t | f
(3 rows)
把CN作為Worker用體現了Citus的靈活性,但是其適用於什麼場景呢?
官方文檔的舉的一個例子是,本地表和參考表可以Join。
這樣的場景我們確實有,那個系統的表設計是:明細表分片,維表作參考表,報表作為本地表。
報表之所以做成本地表,因為要支持高併發訪問,但是又找不到合適的分佈鍵讓所有SQL都以路由方式執行。
報表做成參考表也不合適,副本太多,影響寫入速度,存儲成本也高。
那個系統用的Citus 7.4,還不支持這種用法。當時為了支持報表和參考表的Join,建了一套本地維表,通過觸發器確保本地維表和參考維表同步。
3. 分片隱藏
在Citus MX節點(含作為Worker的CN節點)上,默認shard是隱藏的,即psql的'd'看不到shard表,只能看到邏輯表。
Citus這麼做,可能是擔心有人誤操作shard表。
如果想在Citus MX節點上查看有哪些shard以及shard上的索引。可以使用下面的視圖。
citus_shards_on_worker
citus_shard_indexes_on_worker
或者設置下面的參數
citus.override_table_visibility = false
4. Citus是怎麼隱藏分片的?
Citus的plan hook(distributed_planner)中篡改了pg_table_is_visible
函數,將其替換成citus_table_is_visible
。
這個隱藏只對依賴pg_table_is_visible
函數的地方有效,比如psql的\d
。直接用SQL訪問shard表是不受影響的。
static bool
ReplaceTableVisibleFunctionWalker(Node *inputNode)
{
...
if (functionId == PgTableVisibleFuncId())
{
...
functionToProcess->funcid = CitusTableVisibleFuncId();
...
5. Citus多CN方案的限制和不足
- 不能和多副本同時使用
- Citus MX節點不能訪問本地表
- 不能控制Citus MX節點上不部署參考表