O conector Tair (compatível com Redis OSS) permite ler dados do Tair como tabela de dimensão e gravar no Tair como tabela sink em jobs de streaming Flink SQL.
Visão geral do conector
|
Item |
Detalhes |
|
Tipos de tabela |
Tabela de dimensão, tabela sink |
|
Modo de execução |
Streaming |
|
Formato de dados |
STRING |
|
Métricas |
Tabelas de dimensão: nenhuma. Tabelas sink: |
|
Tipo de API |
API SQL |
|
Atualizações e exclusões de dados em tabelas sink |
Suportado |
Pré-requisitos
Antes de começar, verifique se você possui:
Uma instância Tair (compatível com Redis OSS). Consulte Step 1: Crie an instance.
Uma lista de permissões configurada para a instância. Consulte Step 2: Configure whitelists.
Limitações
Semântica de entrega: O conector suporta apenas entrega com melhor esforço. Não há suporte à semântica exactly-once. Garanta que suas operações de gravação sejam idempotentes.
Tipos de dados de tabela de dimensão: Tabelas de dimensão leem apenas dados STRING e HASHMAP. Todos os campos devem ser do tipo STRING.
Chave primária da tabela de dimensão: Cada tabela de dimensão deve ter exatamente uma chave primária. A cláusula ON em um JOIN de tabela de dimensão deve usar condições de igualdade na chave primária.
Problemas conhecidos
VVR 8.0.9 — Bug de cache do Buffered Writer: A versão VVR 8.0.9 apresenta um problema de cache do Buffered Writer. Como solução alternativa, defina sink.buffer-flush.max-rows como 0 na cláusula WITH da tabela sink.
Sintaxe
CREATE TABLE redis_table (
col1 STRING,
col2 STRING,
PRIMARY KEY (col1) NOT ENFORCED -- Required.
) WITH (
'connector' = 'redis',
'host' = '<yourHost>',
'mode' = 'STRING' -- Required for sink tables.
);
Opções do conector
Opções gerais
Estas opções aplicam-se tanto a tabelas sink quanto a tabelas de dimensão.
| Opção | Tipo de dados | Obrigatório | Padrão | Descrição |
|---|---|---|---|---|
connector |
STRING | Sim | — | Defina como redis. |
host |
STRING | Sim | — | Endereço IP para conexão ao banco de dados ApsaraDB for Redis. Sempre que possível, utilize o endpoint interno. Conexões via internet podem apresentar maior latência ou limitações de largura de banda. |
port |
INT | Não | 6379 |
Número da porta. |
password |
STRING | Não | (string vazia) | Senha de acesso. |
dbNum |
INT | Não | 0 |
Número sequencial do banco de dados. |
clusterMode |
BOOLEAN | Não | false |
Indica se o banco de dados está em modo cluster. |
hostAndPorts |
STRING | Não | — | Pares de host e porta no formato "host1:port1,host2:port2". Obrigatório quando clusterMode é true e alta disponibilidade (HA) é necessária para conexões Jedis ao cluster Redis autogerenciado. Tem precedência sobre host e port. Se clusterMode for true, mas HA não for necessária, configure apenas host e port para especificar um único nó. |
key-prefix |
STRING | Não | — | Prefixo adicionado ao valor da chave primária ao ler de uma tabela de dimensão ou gravar em uma tabela sink. Um delimitador especificado por key-prefix-delimiter separa o prefixo e o valor da chave primária. Requer VVR 8.0.7 ou posterior. |
key-prefix-delimiter |
STRING | Não | — | Delimitador entre o prefixo da chave e o valor da chave primária. |
connection.pool.max-total |
INT | Não | 8 |
Número máximo de conexões que o pool pode alocar. Requer VVR 8.0.9 ou posterior. |
connection.pool.max-idle |
INT | Não | 8 |
Número máximo de conexões ociosas no pool. |
connection.pool.min-idle |
INT | Não | 0 |
Número mínimo de conexões ociosas no pool. |
connection.pool.lifo |
Boolean | Não | true |
Define se as conexões ociosas são alocadas do pool em ordem LIFO. Valores válidos:
Nota: Esta opção é suportada apenas no mecanismo Realtime Compute VVR 11.8.0 e posterior. |
connect.timeout |
DURATION | Não | 3000ms |
Tempo limite para estabelecimento de conexão. |
socket.timeout |
DURATION | Não | 3000ms |
Tempo limite para recebimento de dados do servidor Redis. |
cacert.filepath |
STRING | Não | — | Caminho completo para o certificado SSL/TLS. O arquivo deve estar no formato JKS. Se não definido, a criptografia SSL/TLS fica desativada. Para ativar a criptografia, baixe o certificado CA e faça upload dele como dependência adicional — ele é armazenado no diretório /flink/usrlib. Exemplo: 'cacert.filepath' = '/flink/usrlib/ca.jks'. Requer VVR 11.1 ou posterior. |
Opções de tabela sink
|
Opção |
Tipo de dados |
Obrigatório |
Padrão |
Descrição |
|
|
STRING |
Sim |
— |
Estrutura de dados Redis para a tabela sink. Cinco estruturas são suportadas: STRING, LIST, SET, HASHMAP e SORTEDSET. A instrução DDL deve corresponder à estrutura escolhida. Consulte Estruturas de dados para tabelas sink. |
|
|
BOOLEAN |
Não |
|
Define se os dados HASHMAP são gravados no modo multivalor. Quando |
|
|
BOOLEAN |
Não |
|
Define se as mensagens de retração são ignoradas. Quando |
|
|
LONG |
Não |
|
Tempo de vida (TTL) das chaves inseridas, em milissegundos. |
|
|
INT |
Não |
|
Número máximo de registros (eventos de adição, modificação e exclusão) mantidos no buffer antes do flush. Requer VVR 8.0.9 ou posterior para |
|
|
DURATION |
Não |
|
Intervalo no qual o buffer realiza flush assíncrono. Requer VVR 8.0.9 ou posterior para |
Opções de tabela de dimensão
|
Opção |
Tipo de dados |
Obrigatório |
Padrão |
Descrição |
|
|
STRING |
Não |
|
Tipo de dado a ser lido da tabela de dimensão. |
|
|
STRING |
Não |
— |
Chave Hash fixa usada ao ler dados HASHMAP no modo valor único. Quando definido, declare dois campos: a chave primária mapeia para o campo Hash, e a chave que não é primária mapeia para o valor Hash. |
|
|
STRING |
Não |
|
Política de cache. |
|
|
LONG |
Não |
|
Número máximo de linhas a serem armazenadas em cache. Obrigatório quando |
|
|
LONG |
Não |
— |
Tempo limite do cache em milissegundos. Para |
|
|
BOOLEAN |
Não |
|
Define se resultados vazios (sem correspondência) são armazenados em cache. |
|
|
STRING |
Não |
— |
Períodos durante os quais a política de cache |
|
|
BOOLEAN |
Não |
|
Define se a consulta assíncrona é ativada. Quando |
Notas de uso para a opção cache
ALLrequer VVR 8.0.3 ou posterior.Para versões de VVR 8.0.3 até VVR 11.1 (exclusive),
cache = ALLlê HASHMAP apenas no modo valor único. Na cláusula WITH do DDL, definahashNamecomo o nome da chave; declare Field como chave primária e Value como coluna que não é chave primária.A partir do VVR 11.1,
cache = ALLsuporta o modo multivalor HASHMAP. Especifique a chave Redis como chave primária e declare várias colunas que não são chave primária para cada campo Hash. Definamode = HASHMAPna cláusula WITH.A opção
cachedeve ser usada em conjunto comcacheSizeecacheTTLMs.
Estruturas de dados para tabelas sink
Cada estrutura de dados Redis corresponde a um esquema DDL e comando de gravação específicos.
|
Estrutura de dados |
Esquema DDL |
Comando de gravação |
|
STRING |
Duas colunas: key (STRING), value (STRING) |
|
|
LIST |
Duas colunas: key (STRING), value (STRING) |
|
|
SET |
Duas colunas: key (STRING), value (STRING) |
|
|
HASHMAP (modo valor único, padrão) |
Três colunas: key (STRING), field (STRING), value (STRING) |
|
|
HASHMAP (modo multivalor, |
Múltiplas colunas: key (STRING), seguida de uma coluna por campo Hash — cada nome de coluna é o nome do campo e seu valor é o valor do campo |
|
|
SORTEDSET |
Três colunas: key (STRING), score (DOUBLE), value (STRING) |
|
A opçãoignoreDeletecontrola como as mensagens de retração são tratadas. Quando definida comotrue, as operações de exclusão são ignoradas.
Mapeamentos de tipos de dados
|
Escopo |
Tipo Tair (ApsaraDB for Redis) |
Tipo Flink |
|
Todos os tipos de tabela |
STRING |
STRING |
|
Apenas tabelas sink |
SCORE |
DOUBLE |
O tipo SCORE é usado com dados SORTEDSET. Cada valor em um conjunto ordenado requer uma pontuação DOUBLE, e os valores são classificados em ordem crescente de suas pontuações.
Exemplos
Exemplos de tabela sink
Todos os exemplos de tabela sink leem de uma source Kafka e gravam em uma sink Tair.
Gravar dados STRING
Este exemplo usa user_id como chave Redis e login_time como valor Redis.
CREATE TEMPORARY TABLE kafka_source (
user_id STRING, -- User ID
login_time STRING -- Login time (Unix timestamp)
) WITH (
'connector' = 'kafka',
'topic' = 'user_logins',
'properties.bootstrap.servers' = '<yourKafkaBroker>',
'format' = 'json',
'scan.startup.mode' = 'earliest-offset'
);
CREATE TEMPORARY TABLE redis_sink (
user_id STRING, -- Redis key
login_time STRING, -- Redis value
PRIMARY KEY (user_id) NOT ENFORCED
) WITH (
'connector' = 'redis',
'mode' = 'STRING',
'host' = '<yourHost>',
'port' = '<yourPort>',
'password' = '<yourPassword>'
);
INSERT INTO redis_sink
SELECT * FROM kafka_source;
Gravar dados HASHMAP no modo multivalor
Este exemplo usa order_id como chave Redis e grava product_name, quantity e amount como campos Hash separados.
CREATE TEMPORARY TABLE kafka_source (
order_id STRING, -- Order ID
product_name STRING, -- Product name
quantity STRING, -- Product quantity
amount STRING -- Order amount
) WITH (
'connector' = 'kafka',
'topic' = 'orders_topic',
'properties.bootstrap.servers' = '<yourKafkaBroker>',
'format' = 'json',
'scan.startup.mode' = 'earliest-offset'
);
CREATE TEMPORARY TABLE redis_sink (
order_id STRING, -- Redis key
product_name STRING, -- Hash field: product_name
quantity STRING, -- Hash field: quantity
amount STRING, -- Hash field: amount
PRIMARY KEY (order_id) NOT ENFORCED
) WITH (
'connector' = 'redis',
'mode' = 'HASHMAP',
'flattenHash' = 'true',
'host' = '<yourHost>',
'port' = '<yourPort>',
'password' = '<yourPassword>'
);
INSERT INTO redis_sink
SELECT * FROM kafka_source;
Gravar dados HASHMAP no modo valor único
Este exemplo usa order_id como chave Redis, product_name como campo Hash e quantity como valor Hash.
CREATE TEMPORARY TABLE kafka_source (
order_id STRING, -- Order ID
product_name STRING, -- Product name
quantity STRING -- Product quantity
) WITH (
'connector' = 'kafka',
'topic' = 'orders_topic',
'properties.bootstrap.servers' = '<yourKafkaBroker>',
'format' = 'json',
'scan.startup.mode' = 'earliest-offset'
);
CREATE TEMPORARY TABLE redis_sink (
order_id STRING, -- Redis key
product_name STRING, -- Redis Hash field
quantity STRING, -- Redis Hash value
PRIMARY KEY (order_id) NOT ENFORCED
) WITH (
'connector' = 'redis',
'mode' = 'HASHMAP',
'host' = '<yourHost>',
'port' = '<yourPort>',
'password' = '<yourPassword>'
);
INSERT INTO redis_sink
SELECT * FROM kafka_source;
Exemplos de tabela de dimensão
Todos os exemplos de tabela de dimensão consultam informações de usuário em uma tabela de dimensão Tair e as unem com um stream Kafka.
Ler dados STRING
Este exemplo usa user_id como chave Redis e recupera user_name como valor Redis.
CREATE TEMPORARY TABLE kafka_source (
user_id STRING,
proctime AS PROCTIME()
) WITH (
'connector' = 'kafka',
'topic' = 'user_clicks',
'properties.bootstrap.servers' = '<yourKafkaBroker>',
'format' = 'json',
'scan.startup.mode' = 'earliest-offset'
);
CREATE TEMPORARY TABLE redis_dim (
user_id STRING, -- Redis key
user_name STRING, -- Redis value
PRIMARY KEY (user_id) NOT ENFORCED
) WITH (
'connector' = 'redis',
'host' = '<yourHost>',
'port' = '<yourPort>',
'password' = '<yourPassword>',
'mode' = 'STRING'
);
CREATE TEMPORARY TABLE blackhole_sink (
user_id STRING,
redis_user_id STRING,
user_name STRING
) WITH (
'connector' = 'blackhole'
);
INSERT INTO blackhole_sink
SELECT
t1.user_id,
t2.user_id,
t2.user_name
FROM kafka_source AS t1
JOIN redis_dim FOR SYSTEM_TIME AS OF t1.proctime AS t2
ON t1.user_id = t2.user_id;
Ler dados HASHMAP no modo multivalor
Este exemplo usa user_id como chave Redis e recupera múltiplos campos Hash — user_name, email e register_time — em uma única consulta.
CREATE TEMPORARY TABLE kafka_source (
user_id STRING,
click_time TIMESTAMP(3),
proctime AS PROCTIME()
) WITH (
'connector' = 'kafka',
'topic' = 'user_clicks',
'properties.bootstrap.servers' = '<yourKafkaBroker>',
'format' = 'json',
'scan.startup.mode' = 'earliest-offset'
);
CREATE TEMPORARY TABLE redis_dim (
user_id STRING, -- Redis key
user_name STRING, -- Hash field: user_name
email STRING, -- Hash field: email
register_time STRING, -- Hash field: register_time
PRIMARY KEY (user_id) NOT ENFORCED
) WITH (
'connector' = 'redis',
'host' = '<yourHost>',
'port' = '<yourPort>',
'password' = '<yourPassword>',
'mode' = 'HASHMAP'
);
CREATE TEMPORARY TABLE blackhole_sink (
user_id STRING,
user_name STRING,
email STRING,
register_time STRING,
click_time TIMESTAMP(3)
) WITH (
'connector' = 'blackhole'
);
INSERT INTO blackhole_sink
SELECT
t1.user_id,
t2.user_name,
t2.email,
t2.register_time,
t1.click_time
FROM kafka_source AS t1
JOIN redis_dim FOR SYSTEM_TIME AS OF t1.proctime AS t2
ON t1.user_id = t2.user_id;
Ler dados HASHMAP no modo valor único
Este exemplo usa uma chave Hash fixa (testkey) definida via hashName. A coluna user_id mapeia para o campo Hash, e user_name mapeia para o valor Hash.
CREATE TEMPORARY TABLE kafka_source (
user_id STRING,
proctime AS PROCTIME()
) WITH (
'connector' = 'kafka',
'topic' = 'user_clicks',
'properties.bootstrap.servers' = '<yourKafkaBroker>',
'format' = 'json',
'scan.startup.mode' = 'earliest-offset'
);
CREATE TEMPORARY TABLE redis_dim (
user_id STRING, -- Hash field
user_name STRING, -- Hash value
PRIMARY KEY (user_id) NOT ENFORCED
) WITH (
'connector' = 'redis',
'host' = '<yourHost>',
'port' = '<yourPort>',
'password' = '<yourPassword>',
'hashName' = 'testkey' -- Fixed Hash key
);
CREATE TEMPORARY TABLE blackhole_sink (
user_id STRING,
redis_user_id STRING,
user_name STRING
) WITH (
'connector' = 'blackhole'
);
INSERT INTO blackhole_sink
SELECT
t1.user_id,
t2.user_id,
t2.user_name
FROM kafka_source AS t1
JOIN redis_dim FOR SYSTEM_TIME AS OF t1.proctime AS t2
ON t1.user_id = t2.user_id;