O PL/Proxy é uma extensão do PostgreSQL que encaminha chamadas SQL de um nó de proxy para bancos de dados remotos. No ApsaraDB RDS for PostgreSQL, use-o no modo CLUSTER para distribuir gravações entre shards ou replicar dados entre nós, ou no modo CONNECT para direcionar consultas a um banco de dados específico.
Pré-requisitos
Antes de começar, verifique se você tem:
Uma versão principal do mecanismo compatível com o PL/Proxy — consulte Extensões suportadas pelo ApsaraDB RDS for PostgreSQL
Uma versão secundária do mecanismo atualizada, caso o PL/Proxy não esteja disponível mesmo com uma versão principal compatível — consulte Atualizar a versão secundária do mecanismo
Como funciona
O PL/Proxy opera em um nó de proxy dedicado. Quando um cliente chama uma função PL/Proxy, a extensão intercepta a chamada e a encaminha para um ou mais nós de dados conforme as regras de roteamento definidas no corpo da função.
O modo CLUSTER agrupa nós de dados em um cluster nomeado por meio da instrução SQL/MED CREATE SERVER. Cada função de proxy especifica uma cláusula RUN ON que determina o roteamento da chamada:
|
Cláusula |
Comportamento de roteamento |
|
|
Envia a chamada para um nó de dados selecionado aleatoriamente |
|
|
Transmite a chamada para todos os nós de dados (ideal para replicação SQL ou leituras entre shards) |
O modo CONNECT dispensa a configuração de cluster. Cada função incorpora diretamente uma string de conexão e direciona a consulta para um banco de dados de destino fixo.
Observações de uso
Instâncias RDS na mesma Virtual Private Cloud (VPC) acessam umas às outras diretamente.
Para rotear consultas entre instâncias RDS em VPCs diferentes, use uma instância Elastic Compute Service (ECS) na mesma VPC como proxy intermediário.
A quantidade de nós de dados em um CLUSTER deve ser uma potência de 2 (2, 4, 8, etc.).
Instale a extensão
Conecte-se ao banco de dados do nó de proxy e execute:
CREATE EXTENSION plproxy;
Configure um CLUSTER (apenas modo CLUSTER)
Ignore esta seção se estiver usando o modo CONNECT.
Defina o cluster via CREATE SERVER. Registre cada nó de dados como uma opção (p0, p1, e assim por diante). O número de opções deve ser uma potência de 2.
-
Crie o servidor do cluster e registre seus nós de dados:
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' ); -
Conceda acesso ao cluster:
GRANT USAGE ON FOREIGN SERVER cluster_srv1 TO postgres; -
Crie um mapeamento de usuário para que o PL/Proxy possa autenticar-se nos nós de dados:
CREATE USER MAPPING FOR postgres SERVER cluster_srv1 OPTIONS (user 'postgres');
Configuração de teste
As seções a seguir usam três instâncias RDS para demonstrar ambos os modos.
|
IP |
Função |
Banco de dados |
Nome de usuário |
|
100.xx.xx.136 |
Nó de proxy |
postgres |
postgres |
|
100.xx.xx.72 |
Nó de dados |
pl_db0 |
postgres |
|
11.xx.xx.9 |
Nó de dados |
pl_db1 |
postgres |
Crie uma tabela users em cada nó de dados:
CREATE TABLE users (userid int, name text);
Teste o modo CLUSTER
Sharding horizontal
A cláusula RUN ON ANY roteia cada INSERT aleatoriamente para um dos nós de dados e distribui as gravações pelo cluster.
-
Crie a função
insert_userem cada nó de dados: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; -
Crie a função de proxy no nó de proxy. O PL/Proxy associa chamadas pelo nome da função; portanto, a função de proxy e a função do nó de dados devem ter o mesmo nome.
CREATE OR REPLACE FUNCTION insert_user(i_id int, i_name text) RETURNS integer AS $$ CLUSTER 'cluster_srv1'; RUN ON ANY; $$ LANGUAGE plproxy; -
Crie uma função de leitura no nó de proxy. A instrução
RUN ON ALLconsulta todos os nós de dados e mescla os resultados.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; -
Insira 10 registros a partir do nó de 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'); -
Consulte cada nó de dados para verificar a distribuição dos dados:
Como
RUN ON ANYroteia gravações aleatoriamente, a distribuição é desigual.-- On pl_db0 SELECT * FROM users; userid | name --------+-------- 1001 | Sven 1003 | Steve 1004 | lottu 1005 | rax 1006 | ak 1007 | jack 1008 | molica 1009 | pg (8 rows) -- On pl_db1 SELECT * FROM users; userid | name --------+-------- 1002 | Marko 1010 | oracle (2 rows) -
Leia todas as linhas pelo nó de 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 rows)
Replicação SQL
A diretiva RUN ON ALL transmite cada gravação para todos os nós de dados e os mantém sincronizados.
-
Crie uma função
trunc_userem cada nó de dados e também no nó de proxy:-- On pl_db0 and pl_db1 CREATE OR REPLACE FUNCTION trunc_user() RETURNS integer AS $$ TRUNCATE TABLE users; SELECT 1; $$ LANGUAGE SQL; -- On the proxy node CREATE OR REPLACE FUNCTION trunc_user() RETURNS SETOF integer AS $$ CLUSTER 'cluster_srv1'; RUN ON ALL; $$ LANGUAGE plproxy; -
Trunque a tabela em todos os nós:
SELECT trunc_user(); trunc_user ------------ 1 1 (2 rows) -
Crie a função de inserção com replicação no nó de proxy. O parâmetro
TARGET insert_userinstrui o PL/Proxy a chamar a funçãoinsert_user(já definida nos nós de dados) em cada nó: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; -
Insira 4 registros:
SELECT insert_user_2(1004, 'lottu'); SELECT insert_user_2(1005, 'rax'); SELECT insert_user_2(1006, 'ak'); SELECT insert_user_2(1007, 'jack'); -
Verifique se ambos os nós de dados contêm dados idênticos:
-- On pl_db0 SELECT * FROM users; userid | name --------+------- 1004 | lottu 1005 | rax 1006 | ak 1007 | jack (4 rows) -- On pl_db1 SELECT * FROM users; userid | name --------+------- 1004 | lottu 1005 | rax 1006 | ak 1007 | jack (4 rows) -
Leia os dados pelo nó de proxy usando
RUN ON ANY— como todos os nós possuem dados idênticos, qualquer um deles retorna o resultado completo: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 rows)
Teste o modo CONNECT
O modo CONNECT direciona uma consulta para um único banco de dados especificado, sem exigir configuração de cluster. Incorpore a string de conexão diretamente na função.
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 rows)
Escolha um modo
|
Modo CLUSTER |
Modo CONNECT |
|
|
Indicado quando |
Você precisa de sharding horizontal ou deseja replicar gravações entre nós |
É necessário consultar um banco de dados remoto específico via string de conexão |
|
Configuração de cluster necessária |
Sim ( |
Não |
|
Restrição de quantidade de nós de dados |
Deve ser uma potência de 2 |
Nenhuma |
|
Roteamento |
|
String de conexão fixa por função |
|
Caso de uso típico |
Distribuição de grandes conjuntos de dados entre várias instâncias RDS |
Consultas entre instâncias ou federação ad-hoc |
Próximos passos
Para obter a referência completa da linguagem PL/Proxy, consulte o Tutorial do PL/Proxy.
Para verificar quais outras extensões estão disponíveis para sua instância, consulte Extensões suportadas pelo ApsaraDB RDS for PostgreSQL.