1. 程式人生 > >利用 citus 支援地理大資料

利用 citus 支援地理大資料

PostgreSQL有一些極限:

Maximum size for a database? unlimited (32 TB databases exist)
Maximum size for a table? 32 TB
Maximum size for a row? 400 GB
Maximum size for a field? 1 GB
Maximum number of rows in a table? unlimited
Maximum number of columns in a table? 250-1600 depending on column types
Maximum number of indexes on a table? unlimited

使用單節點的PostgreSQL很多情況下是OK的,但32T的表放在一個機器節點上,查詢一條記錄,掃描一遍索引就要耗時很久。一般的做法是水平和垂直分表,手動分表對應用的侵入性較大,往往需要維護訪問邏輯。今天介紹的Citus就可以不用更改應用邏輯,無痛遷移,還能帶來平行計算的bouns,有人可能會說,PostgreSQL9.6就加入了並行執行,但日常處理地理資料,就少不了PostGIS,而PostgreSQL的並行執行對涉及PostGIS的查詢就不行了(使用explain查詢執行計劃即可看出),而Citus卻能充分調動所有資源並行執行。

同等CPU和RAM,原來單節點CPU和RAM等於worker的總和,叢集相對於原來一般會有2~3倍的效能提升。主要原因是分表提升了資源利用率,並且索引更小。

Citus是什麼

Citus是一個PostgreSQL擴充套件,主要用於水平自動分表,有一個類似擴充套件pg_shard已是deprecation狀態,推薦使用Citus。Citus是單coordinator,多worker架構,coordinator統籌協調工作,worker是真正幹活的。支援分散式冗餘儲存,並行查詢計算。

三個主要使用場景:

  • 資料分散式儲存的應用(Multi-tenant Application),實測單節點vs四臺citus叢集入庫20G資料有7倍的差距;
  • 實時分析(Real-Time Dashboards),只適合節點之間IO非常小的場景;
  • 時間序列資料的查詢分析(Timeseries Data
    ),不甚瞭解。

Citus的特點

  1. 從單節點資料庫到Citus叢集無需更改應用邏輯,只需資料遷移即可;
  2. 並行執行查詢提高效率,且效能隨著節點數量增加線性增加。但不適用於需要各節點彙總資料,涉及大量IO的情景,這樣反而會抵消並行執行省下的時間。

Citus通過使用鉤子和擴充套件API來實現PostgreSQL的分散式儲存和平行計算,因此很多PostgreSQL擴充套件也能使用citus提供的能力,包括PostGIS,這就為我們使用Citus叢集來管理和分析地理大資料提供了可能。但是需要注意,要配合Citus使用其它擴充套件,Citus必須是第一個啟用的擴充套件,其次,必須在coordinator和worker節點都安裝相應擴充套件。所以我們需要在所有機器節點上安裝Citus和PostGIS。

嘗試

本示例使用了6臺機器做叢集,1臺coordinator,5臺worker

  1. 首先在各個節點上安裝PostgreSQL,安裝Citus擴充套件,安裝PostGIS擴充套件;
  2. 修改PostgreSQL的配置,啟動時預載入citus,並配置各個節點的PostgreSQL互相聯通,可互相訪問;
  3. 啟動資料庫,啟用擴充套件。
systemctl start postgresql-10.service
systemctl enable postgresql-10.service
psql -U postgers -c "create extension citus;"
psql -U postgers -c "create extension postgis;"

新增worker

在coordinator節點新增所有worker節點,

psql -U postgres -c "select * from master_add_node('ip-or-name', port);"

最後列出所有節點檢查是否新增成功,

psql -U postgres -c "SELECT * FROM master_get_active_worker_nodes();"

遷移資料

遷移現有的資料到citus叢集

允許服務間斷的場景:

首先將原來的資料備份,將一張表由單表調整為distributed,需要在灌資料之前宣告,所以我們需要三個步驟:首先備份並恢復表結構,然後宣告表為distributed,最後備份並恢復資料,此時資料會分佈到各個worker。

  • 備份表結構

pg_dump -Fc --no-owner --schema-only --dbname db_name > db_name_schema.back

pg_restore --dbname db_name db_name_schema.back

  • 宣告distributed

select * from create_distributed_table('table_name', 'id')

  • 灌資料

pg_dump -Fc --no-owner --data-only --dbname db_name > db_name_data.back

pg_restore --dbname db_name db_name_data.back

不允許服務間斷

可以使用PostgreSQL的logical replication,將在用的老資料庫指向Citus主節點,這樣新老資料庫處於同步狀態,然後統一將服務的資料庫連線地址切換到Citus。

測試效能

All things done!接下來進行一些簡單的測試。

匯入資料與資料分佈

資料量: 122608100 個多邊形,恢復資料耗時7分鐘,每個節點 9.1 G 資料;這些資料恢復到一臺相同配置單主機的 PostgreSQL 資料庫資料量是,耗時 55分鐘,28 G 資料。將近8倍的差距,但是我們注意到資料是有一定程度的冗餘的,因此citus可以承受單節點的資料丟失。

緩衝區操作處理時間

對1.2億的資料進行6米半徑的緩衝區分析,並將結果存入資料庫

insert into buffer_result (id, the_geom) select id, st_buffer(the_geom, 6) as the_geom from table_name;

citus叢集,56分鐘;單機,120分鐘,差距並不明顯,原因其實我們上面提到過,計算結果需要彙總,且涉及到了大量的IO,觀察處理過程注意到,15分鐘計算完成,25分鐘彙總資料,16分鐘寫入結果,而單機不需要彙總資料。

不涉及彙總的操作

對1.2億多邊形統計總節點數:

select sum(st_npoints(the_geom)) from table_name;

citus叢集耗時1.7秒,而單節點耗時50秒,差距很明顯。

總結

以上的測試中,資料庫並沒有進行很好的調優,是比較粗糙的結果,但也足以說明問題。

  • 資料分散式儲存的應用(Multi-tenant Application),實測單節點vs四臺citus叢集入庫20G資料有7倍的差距;
  • 實時分析(Real-Time Dashboards),只適合節點之間IO非常小的場景。