PL/Proxy adalah ekstensi PostgreSQL yang mengarahkan panggilan SQL dari node proxy ke database remote. Di ApsaraDB RDS for PostgreSQL, ekstensi ini dapat digunakan dalam mode CLUSTER untuk mendistribusikan operasi tulis ke beberapa shard atau mereplikasi data di berbagai node, serta dalam mode CONNECT untuk mengarahkan kueri ke database tertentu.
Prasyarat
Sebelum memulai, pastikan Anda telah memiliki:
Versi mesin utama yang mendukung PL/Proxy — lihat Ekstensi yang didukung oleh ApsaraDB RDS for PostgreSQL
Versi mesin minor terbaru jika PL/Proxy tidak tersedia meskipun versi mesin utamanya didukung — lihat Perbarui versi mesin minor
Cara kerja
PL/Proxy berjalan pada node proxy khusus. Ketika klien memanggil fungsi PL/Proxy, PL/Proxy mencegat panggilan tersebut dan meneruskannya ke satu atau beberapa node data berdasarkan aturan routing yang tertanam dalam isi fungsi.
Mode CLUSTER mengelompokkan node data ke dalam kluster bernama menggunakan pernyataan SQL/MED CREATE SERVER. Setiap fungsi proxy menentukan klausa RUN ON yang mengatur cara panggilan diarahkan:
| Klausa | Perilaku routing |
|---|---|
RUN ON ANY | Mengirim panggilan ke node data yang dipilih secara acak |
RUN ON ALL | Menyiarkan panggilan ke semua node data (gunakan untuk replikasi SQL atau pembacaan lintas shard) |
Mode CONNECT melewati konfigurasi kluster. Setiap fungsi menyematkan string koneksi secara langsung dan mengarahkan kueri ke database target tetap.
Catatan penggunaan
Instans RDS dalam virtual private cloud (VPC) yang sama dapat saling mengakses secara langsung.
Untuk mengarahkan kueri antar instans RDS di VPC berbeda, tempatkan instans Elastic Compute Service (ECS) di VPC yang sama sebagai proxy perantara.
Jumlah node data dalam CLUSTER harus merupakan pangkat dari 2 (2, 4, 8, dan seterusnya).
Instal ekstensi
Hubungkan ke database node proxy dan jalankan:
CREATE EXTENSION plproxy;Siapkan CLUSTER (hanya untuk mode CLUSTER)
Lewati bagian ini jika Anda menggunakan mode CONNECT.
Kluster didefinisikan dengan CREATE SERVER. Setiap node data didaftarkan sebagai opsi (p0, p1, dan seterusnya). Jumlah opsi harus merupakan pangkat dari 2.
Buat server kluster dan daftarkan node data Anda:
CREATE SERVER cluster_srv1 FOREIGN DATA WRAPPER plproxy OPTIONS ( connection_lifetime '1800', disable_binary '1', p0 'dbname=pl_db0 host=100.xxx.xxx.72 port=5678', p1 'dbname=pl_db1 host=11.xxx.xxx.9 port=5678' );Berikan akses ke kluster:
GRANT USAGE ON FOREIGN SERVER cluster_srv1 TO postgres;Buat pemetaan pengguna agar PL/Proxy dapat melakukan autentikasi ke node data:
CREATE USER MAPPING FOR postgres SERVER cluster_srv1 OPTIONS (user 'postgres');
Uji coba pengaturan
Bagian berikut menggunakan tiga instans RDS untuk mendemonstrasikan kedua mode.
| IP | Peran | Database | Username |
|---|---|---|---|
| 100.xx.xx.136 | Node proxy | postgres | postgres |
| 100.xx.xx.72 | Node data | pl_db0 | postgres |
| 11.xx.xx.9 | Node data | pl_db1 | postgres |
Buat tabel users di setiap node data:
CREATE TABLE users (userid int, name text);Uji coba mode CLUSTER
Sharding horizontal
RUN ON ANY mengarahkan setiap perintah INSERT secara acak ke salah satu node data, sehingga mendistribusikan operasi tulis di seluruh kluster.
Buat fungsi
insert_userdi setiap node data:CREATE OR REPLACE FUNCTION insert_user(i_id int, i_name text) RETURNS integer AS $$ INSERT INTO users (userid, name) VALUES ($1, $2); SELECT 1; $$ LANGUAGE SQL;Buat fungsi proxy di node proxy. PL/Proxy mencocokkan panggilan berdasarkan nama fungsi, sehingga fungsi proxy dan fungsi di node data harus memiliki nama yang sama.
CREATE OR REPLACE FUNCTION insert_user(i_id int, i_name text) RETURNS integer AS $$ CLUSTER 'cluster_srv1'; RUN ON ANY; $$ LANGUAGE plproxy;Buat fungsi baca di node proxy.
RUN ON ALLmengkueri setiap node data dan menggabungkan hasilnya.CREATE OR REPLACE FUNCTION get_user_name() RETURNS TABLE(userid int, name text) AS $$ CLUSTER 'cluster_srv1'; RUN ON ALL; SELECT userid, name FROM users; $$ LANGUAGE plproxy;Masukkan 10 catatan dari node proxy:
SELECT insert_user(1001, 'Sven'); SELECT insert_user(1002, 'Marko'); SELECT insert_user(1003, 'Steve'); SELECT insert_user(1004, 'lottu'); SELECT insert_user(1005, 'rax'); SELECT insert_user(1006, 'ak'); SELECT insert_user(1007, 'jack'); SELECT insert_user(1008, 'molica'); SELECT insert_user(1009, 'pg'); SELECT insert_user(1010, 'oracle');Kueri setiap node data untuk melihat bagaimana data didistribusikan:
RUN ON ANYmengarahkan operasi tulis secara acak, sehingga distribusinya tidak merata.-- Di pl_db0 SELECT * FROM users; userid | name --------+-------- 1001 | Sven 1003 | Steve 1004 | lottu 1005 | rax 1006 | ak 1007 | jack 1008 | molica 1009 | pg (8 baris) -- Di pl_db1 SELECT * FROM users; userid | name --------+-------- 1002 | Marko 1010 | oracle (2 baris)Baca kembali semua baris melalui node proxy:
SELECT userid, name FROM get_user_name(); userid | name --------+-------- 1001 | Sven 1003 | Steve 1004 | lottu 1005 | rax 1006 | ak 1007 | jack 1008 | molica 1009 | pg 1002 | Marko 1010 | oracle (10 baris)
Replikasi SQL
RUN ON ALL menyiarkan setiap operasi tulis ke semua node data, sehingga menjaga semua node tetap sinkron.
Buat fungsi
trunc_userdi setiap node data dan di node proxy:-- Di pl_db0 dan pl_db1 CREATE OR REPLACE FUNCTION trunc_user() RETURNS integer AS $$ TRUNCATE TABLE users; SELECT 1; $$ LANGUAGE SQL; -- Di node proxy CREATE OR REPLACE FUNCTION trunc_user() RETURNS SETOF integer AS $$ CLUSTER 'cluster_srv1'; RUN ON ALL; $$ LANGUAGE plproxy;Truncate tabel di semua node:
SELECT trunc_user(); trunc_user ------------ 1 1 (2 baris)Buat fungsi insert replikasi di node proxy.
TARGET insert_usermemberi tahu PL/Proxy untuk memanggil fungsiinsert_user(yang sudah didefinisikan di node data) di setiap node:CREATE OR REPLACE FUNCTION insert_user_2(i_id int, i_name text) RETURNS SETOF integer AS $$ CLUSTER 'cluster_srv1'; RUN ON ALL; TARGET insert_user; $$ LANGUAGE plproxy;Masukkan 4 catatan:
SELECT insert_user_2(1004, 'lottu'); SELECT insert_user_2(1005, 'rax'); SELECT insert_user_2(1006, 'ak'); SELECT insert_user_2(1007, 'jack');Verifikasi bahwa kedua node data berisi data yang identik:
-- Di pl_db0 SELECT * FROM users; userid | name --------+------- 1004 | lottu 1005 | rax 1006 | ak 1007 | jack (4 baris) -- Di pl_db1 SELECT * FROM users; userid | name --------+------- 1004 | lottu 1005 | rax 1006 | ak 1007 | jack (4 baris)Baca melalui node proxy menggunakan
RUN ON ANY— karena semua node menyimpan data yang identik, node mana pun akan mengembalikan hasil lengkap:CREATE OR REPLACE FUNCTION get_user_name_2() RETURNS TABLE(userid int, name text) AS $$ CLUSTER 'cluster_srv1'; RUN ON ANY; SELECT userid, name FROM users; $$ LANGUAGE plproxy; SELECT userid, name FROM get_user_name_2(); userid | name --------+------- 1004 | lottu 1005 | rax 1006 | ak 1007 | jack (4 baris)
Uji coba mode CONNECT
Mode CONNECT mengarahkan kueri ke satu database tertentu tanpa memerlukan pengaturan kluster. Sematkan string koneksi langsung di dalam fungsi.
CREATE OR REPLACE FUNCTION get_user_name_3()
RETURNS TABLE(userid int, name text) AS $$
CONNECT 'dbname=pl_db0 host=100.81.137.72 port=56789';
SELECT userid, name FROM users;
$$ LANGUAGE plproxy;
SELECT userid, name FROM get_user_name_3();
userid | name
--------+-------
1004 | lottu
1005 | rax
1006 | ak
1007 | jack
(4 baris)Pilih mode
| Mode CLUSTER | Mode CONNECT | |
|---|---|---|
| Gunakan saat | Anda membutuhkan sharding horizontal atau ingin mereplikasi operasi tulis di berbagai node | Anda perlu mengkueri database remote tertentu berdasarkan string koneksi |
| Diperlukan pengaturan kluster | Ya (CREATE SERVER, pemetaan pengguna) | Tidak |
| Batasan jumlah node data | Harus merupakan pangkat dari 2 | Tidak ada |
| Routing | RUN ON ANY (acak) atau RUN ON ALL (siaran) | String koneksi tetap per fungsi |
| Kasus penggunaan umum | Distribusi dataset besar di beberapa instans RDS | Kueri lintas instans atau federasi ad-hoc |
Langkah selanjutnya
Untuk referensi lengkap bahasa PL/Proxy, lihat tutorial PL/Proxy.
Untuk memeriksa ekstensi lain yang tersedia untuk instans Anda, lihat Ekstensi yang didukung oleh ApsaraDB RDS for PostgreSQL.