利用 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的特點
- 從單節點資料庫到Citus叢集無需更改應用邏輯,只需資料遷移即可;
- 並行執行查詢提高效率,且效能隨著節點數量增加線性增加。但不適用於需要各節點彙總資料,涉及大量IO的情景,這樣反而會抵消並行執行省下的時間。
Citus通過使用鉤子和擴充套件API來實現PostgreSQL的分散式儲存和平行計算,因此很多PostgreSQL擴充套件也能使用citus提供的能力,包括PostGIS,這就為我們使用Citus叢集來管理和分析地理大資料提供了可能。但是需要注意,要配合Citus使用其它擴充套件,Citus必須是第一個啟用的擴充套件,其次,必須在coordinator和worker節點都安裝相應擴充套件。所以我們需要在所有機器節點上安裝Citus和PostGIS。
嘗試
本示例使用了6臺機器做叢集,1臺coordinator,5臺worker
- 首先在各個節點上安裝PostgreSQL,安裝Citus擴充套件,安裝PostGIS擴充套件;
- 修改PostgreSQL的配置,啟動時預載入citus,並配置各個節點的PostgreSQL互相聯通,可互相訪問;
- 啟動資料庫,啟用擴充套件。
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非常小的場景。