Ir para o conteúdo principal
Engenharia

Apresentando o Apache Spark® 4.3 - Já disponível no Databricks Runtime 19

Processamento em tempo real com estado, pipelines que preservam o histórico e desenvolvimento mais rápido de dados pequenos

por Jungtaek Lim, Wenchen Fan, Andreas Neumann, Serge Rielau, Hyukjin Kwon, Jerry Peng, DB Tsai, Daniel Tenedorio, Xiao Li e Reynold Xin

  • Traga estado para o Modo em Tempo Real: O Modo em Tempo Real adiciona agregação de streaming, desduplicação e processamento com estado personalizado, alcançando latência ponta a ponta P99 inferior a 150 ms em três benchmarks representativos usando APIs familiares do Structured Streaming.
  • ** Preserve o histórico com o Auto CDC SCD Tipo 2:** Acompanhe como os registros mudam ao longo do tempo por meio de Python, SQL e Spark Connect, simplificando pipelines de preservação de histórico para relatórios, auditoria e análise histórica.
  • Itere mais rápido e crie com APIs mais ricas: O Projeto Feather reduz a sobrecarga de execução para consultas de dados pequenos elegíveis, enquanto as melhorias no Spark Connect, Python e SQL tornam os aplicativos de dados e IA mais fáceis de desenvolver, depurar e operar.

Introdução

O Apache Spark 4.3 traz o processamento com estado para o Real-Time Mode, alcançando uma latência ponta a ponta P99 inferior a 150 ms em três benchmarks representativos com estado. Agregações de streaming, deduplicação e processamento personalizado com estado agora podem ser executados no modo de execução de baixa latência do Structured Streaming, estendendo-o para aplicações que precisam lembrar o contexto entre eventos.

O impacto vai além de pipelines mais rápidas. Para cargas de trabalho compatíveis, você não precisa mais de um mecanismo de streaming separado apenas para atingir latência em escala de milissegundos. Da detecção de fraudes à atividade de usuário atualizada continuamente e monitoramento de dispositivos, os desenvolvedores podem criar aplicações com estado usando as APIs familiares do Structured Streaming no mesmo mecanismo aberto que usam para processamento em lote, análise e IA.

O streaming em tempo real com estado é o destaque do Spark 4.3, mas as melhorias se estendem por todo o mecanismo. O lançamento oferece cinco benefícios principais:

  • Crie aplicações em tempo real com estado: Use agregação de streaming, deduplicação e transformWithState no Real-Time Mode para manter o contexto à medida que os eventos chegam.
  • Preserve o histórico com SCD Type 2 Auto CDC: Acompanhe como os registros mudam ao longo do tempo usando Python, SQL e Spark Connect, com menos lógica personalizada de processamento de alterações
  • Itere mais rápido em dados pequenos: O Project Feather tem como alvo a sobrecarga de execução desnecessária, enquanto o cache nativo do Arrow oferece suporte a um reuse de dados mais eficiente.
  • Conecte mais aplicações ao Spark: As melhorias na observabilidade do Spark Connect, na integração JDBC e no Python tornam a execução remota mais fácil de desenvolver e operar.
  • Expresse análises mais avançadas diretamente em SQL: Transformações VARIANT, JSON_TABLE, junções temporais e uma visualização de carimbo de data/hora em nanossegundos estendem o processamento nativo de dados aninhados e orientados no tempo.

Juntas, essas mudanças ajudam os desenvolvedores a usar um único mecanismo aberto para explorar dados, manter o contexto em alteração e alimentar aplicações analíticas e de IA.

O Spark 4.3 também marca o início de um cronograma trimestral de lançamento de recursos, passando de um lançamento a cada seis meses para um a cada três meses. Esse ciclo mais curto coloca as melhorias concluídas nas mãos dos usuários mais rapidamente e oferece à comunidade oportunidades mais frequentes de fornecer feedback e moldar o que vem a seguir.

Streaming em tempo real: aplicações com estado com latência em escala de milissegundos

Do processamento de eventos à manutenção de contexto

Um sinal de fraude depende não apenas da transação mais recente, mas também da atividade que a precedeu. A personalização precisa refletir o comportamento recente do usuário. O monitoramento de dispositivos precisa atualizar contadores e agregações à medida que novas leituras chegam. Essas aplicações precisam de baixa latência e de estado.

O Spark 4.3 estende o Real-Time Mode para esses padrões de processamento com estado, tornando-se um mecanismo de streaming completo. Ele adiciona suporte para agregação de streaming, dropDuplicates e transformWithState para Scala/Java (SPARK-58635, SPARK-57228). Os desenvolvedores podem manter o estado com chave e atualizar os resultados usando o modelo de programação existente do Structured Streaming, em vez de adotar outro mecanismo exclusivamente para obter menor latência.

Latência P99 abaixo de 150 ms em três benchmarks com estado

Nos benchmarks relatados em SPARK-58884, todas as três cargas de trabalho representativas com estado alcançaram uma latência ponta a ponta P99 abaixo de 150 milissegundos:

Carga de trabalho com estadoLatência ponta a ponta P99
dropDuplicates136 ms
Agregação de janela139 ms
transformWithState141 ms

Esses resultados demonstram execução de baixa latência em deduplicação, agregação com janela e processamento personalizado com estado. Eles são medições das três cargas de trabalho testadas, e não uma garantia de latência para todos os pipelines.

APIs familiares, execução de baixa latência

O Real-Time Mode se baseia no Structured Streaming em vez de introduzir um modelo de programação separado. Os operadores com estado continuam usando o armazenamento de estado e os mecanismos de ponto de verificação existentes do Spark para durabilidade e recuperação.

Exemplo: mantenha uma contagem contínua para cada dispositivo. Dado um DataFrame de streaming apoiado por Kafka events com uma coluna device_id:

Se os eventos chegarem para os dispositivos A, A e B, o Spark mantém o estado e atualiza as contagens para A=2 e B=1. Quando outro evento para A chega, seu estado é atualizado para A=3.

Um mecanismo de execução criado para o fluxo contínuo de dados

O suporte ao Real-Time Mode com estado exigiu uma mudança fundamental na forma como o Spark agenda e conecta os estágios. Com um embaralhamento (shuffle) de bloqueio tradicional, um estágio produtor deve terminar antes que seu estágio subsequente possa começar. Esse modelo não consegue suportar o fluxo contínuo de dados entre tarefas de streaming de longa execução.

O Spark 4.3 introduz o agendamento de estágios concorrentes nativo e embaralhamentos (shuffles) em pipeline, permitindo que os estágios produtores e consumidores sejam executados ao mesmo tempo (SPARK-54699, SPARK-58076, SPARK-56664). O Streaming Shuffle implementa essa capacidade para o Real-Time Mode, transferindo registros de forma incremental para a tarefa subsequente responsável por cada chave, em vez de esperar que todo o estágio produtor termine.

Conceitualmente, a execução muda de:

Estágio produtor → materializar embaralhamento → estágio consumidor

para:

Estágio produtor ⇄ embaralhamento de streaming ⇄ estágio consumidor

O Spark 4.3 adiciona PipelinedShuffleDependency, um novo tipo de dependência de embaralhamento que permite que os consumidores comecem a ler enquanto os produtores ainda estão em execução (SPARK-58185). O agendador trata os estágios conectados por essas dependências como um grupo em pipeline, uma unidade de agendamento coordenada. Seus estágios são agendados juntos, e uma falha em um estágio faz com que todo o grupo falhe (SPARK-58263, SPARK-58398). Em suma, eles são executados juntos e falham juntos.

Como todos os estágios em um grupo em pipeline são executados simultaneamente, o Spark admite o grupo apenas quando há slots de tarefa suficientes disponíveis para todas as suas tarefas. Caso contrário, ele falha rapidamente em vez de travar.

O Spark direciona cada embaralhamento para um gerenciador de embaralhamento com base no seu tipo de dependência:

  • Um ShuffleDependency regular usa um gerenciador de embaralhamento de bloqueio, que materializa toda a saída do embaralhamento antes que os estágios subsequentes a leiam. SortShuffleManager é a implementação integrada.
  • Um PipelinedShuffleDependency usa um gerenciador de shuffle em pipeline, o que torna a saída disponível conforme é produzida. O StreamingShuffleManager é a implementação integrada (SPARK-57141).

O tipo de dependência define o contrato de execução; o gerenciador de shuffle fornece o mecanismo de transferência de dados. O escalonador coordena estágios em pipeline sem precisar saber qual carga de trabalho os criou.

Esta base vai além do Modo em Tempo Real. O escalonamento de estágios concorrentes, a troca de dados em pipeline e a execução coordenada são recursos genéricos do motor Spark, e não uma infraestrutura de streaming isolada. No Spark 4.3, eles permitem o processamento com estado de baixa latência. No longo prazo, eles fornecem uma base para outras cargas de trabalho que precisam ir além do modelo tradicional de execução etapa por etapa.

Para ver o histórico sobre o design e os cenários de aplicação do Modo em Tempo Real, consulte a introdução ao Modo em Tempo Real. Essa publicação descreve a implementação do Databricks; o escopo dos recursos do Spark 4.3 e os resultados dos benchmarks discutidos aqui são os listados acima.

Project Feather: Iteração Mais Rápida em Dados Pequenos

O desenvolvimento assistido por LLM geralmente segue um ciclo de feedback curto: gerar uma transformação, executá-la em uma amostra, inspecionar os resultados e refinar o código. Cada iteração pode processar apenas um arquivo pequeno ou algumas linhas, mas o escalonamento de tarefas e o shuffle podem custar mais do que a própria computação.

O Project Feather tem como alvo essa sobrecarga de execução fixa, tornando o Spark mais ágil para explorar e validar códigos SQL e DataFrame em pequenos conjuntos de dados. Os desenvolvedores podem usar as mesmas APIs ao passar de uma amostra para cargas de trabalho maiores, seja escrevendo o código por conta própria ou trabalhando com um assistente de IA.

O Spark 4.3 introduz a execução opcional de tarefa única sem shuffle para fragmentos de consulta elegíveis, pequenos e de partição única (SPARK-57851). Quando um exame qualificável relata que sua saída já está em uma partição, as operações downstream compatíveis podem evitar um shuffle desnecessário.

Exemplo: Execute e inspecione uma pequena agregação. Use um pequeno conjunto de dados Parquet armazenado como um único arquivo, com uma coluna de categoria:

Seis casos:

category, Exchange, SPARK_LOCAL_CONNECT_REUSE=1, zip, counter_diff and jaro_winkler_similarity.

O resultado é uma contagem por categoria. Para uma consulta elegível, o plano físico pode omitir o `Exchange` que, caso contrário, introduziria um shuffle. Isso dá suporte ao mesmo fluxo de trabalho de execução e inspeção, independentemente de a transformação ter sido escrita por um desenvolvedor ou sugerida por um assistente de código.

Com os limites de elegibilidade padrão, as varreduras de arquivos qualificadas leem um pequeno arquivo não vazio que cabe em uma única partição, enquanto as relações locais em memória qualificadas contêm até 1.000 linhas. As formas de consulta compatíveis incluem varreduras selecionadas, agregações, operações distintas, janelas, ordenações e limites.

O Feather também adiciona o cache opcional de Dataset nativo do Arrow (SPARK-57268), armazenando lotes em cache no formato Arrow com compressão e estatísticas de coluna. Entradas baseadas em Arrow podem evitar conversões desnecessárias, dando suporte a fluxos de trabalho que exploram repetidamente os mesmos dados. Tanto a otimização de tarefa única quanto o cache do Arrow são opcionais. Para ativá-los, defina a configuração estática spark.sql.cache.serializer=org.apache.spark.sql.execution.columnar.ArrowCachedBatchSerializer ao iniciar uma nova aplicação Spark. Um rebalanceamento local em processo mais amplo é um trabalho futuro planejado para o próximo lançamento (SPARK-57399).

Essas melhorias são apenas o começo. A comunidade Spark continuará investindo no desempenho com dados pequenos em versões futuras, reduzindo a sobrecarga de execução e encurtando os ciclos de feedback para exploração interativa e desenvolvimento assistido por LLM.

SCD Tipo 2 no Auto CDC de Código Aberto: Preserve o Histórico Conforme os Dados Mudam

Uma tabela de estado atual pode informar onde um cliente mora hoje, mas não a qual região ele pertencia quando um pedido foi feito. Relatórios, auditoria e análise histórica geralmente precisam de ambos. O Spark 4.3 adiciona suporte completo a Slowly Changing Dimension (SCD) Tipo 2 ao Auto CDC (SPARK-56249), para que os pipelines possam rastrear o histórico de cada registro em vez de sobrescrever o valor mais recente a cada alteração. O recurso está disponível por meio de Python, SQL e Spark Connect (SPARK-58321, SPARK-58247, SPARK-58261) e permite que os usuários apliquem alterações automaticamente em vez de realizarem operações de mesclagem manuais.

Exemplo: Acompanhe o status e a região do cliente ao longo do tempo. Dado um customer_changes pipeline de origem com ID de cliente, horário do evento, status e região:

Como alternativa, isso pode ser expresso em SQL:

Em uma tabela de saída SCD-2, cada chave exclusiva é representada por uma sequência de registros, cada um marcando o início e o fim de sua validade usando duas colunas de metadados extras, __START_AT e __END_AT. Por exemplo, quando um registro de alteração indica que o cliente com id 17 mudou da região West para East, o pipeline retém o registro com a região anterior West e marca seu término como o horário do evento do registro de alteração; ele insere um novo registro com a região East e o horário do evento do registro como seu início. Uma análise pode então usar a região aplicável no ponto relevante da sequência de horários do evento.

Nos bastidores, o Auto CDC conecta a definição de fluxo declarativa à derivação de esquema de destino e ao processamento de stream SCD Tipo 2 dedicado (SPARK-58319, SPARK-57395, SPARK-58321). As chaves identificam a entidade, a ordenação determina a ordem das alterações e as colunas de rastreamento de histórico especificam quais alterações de atributos criam versões históricas. O motor também valida colunas reservadas, tipos de sequenciamento e configuração de rastreamento de histórico (SPARK-57251, SPARK-58313, SPARK-58391) e reconcilia micro-lotes menores com um esquema de destino evoluído (SPARK-58418).

O Auto CDC aplica cada micro-batch ao destino usando o MERGE; portanto, a tabela de destino deve estar em um catálogo cujo conector implemente operações de nível de linha do Data Source V2. Os formatos de arquivo integrados do Spark, incluindo o Parquet, não se qualificam. Portanto, uma escolha comum é o Iceberg.

Spark Connect: Mais Fácil de Desenvolver, Observar e Operar

Aplicações e agentes de IA precisam invocar o Spark a partir de seus próprios processos, gerenciar sessões e conectar uma solicitação com falha ao trabalho em execução no servidor. O Spark 4.3 aprimora o Spark Connect para esses fluxos de trabalho com visibilidade de sessão e operação, atribuição de solicitações e suporte a clientes mais abrangente.

O Spark Connect envia operações de DataFrame como planos lógicos via gRPC, executa-os através do mecanismo Spark do servidor e transmite os resultados de volta em lotes do Arrow. O Spark 4.3 adiciona endpoints REST para listar e inspecionar sessões e operações do Connect, além de IDs de operação para rastrear a execução entre clientes e o servidor (SPARK-57941, SPARK-58547). Para o desenvolvimento local com PySpark em sistemas POSIX, a opção experimental `SPARK_LOCAL_CONNECT_REUSE=1` reutiliza um servidor Connect persistente entre execuções, evitando a sobrecarga de inicializações repetidas (SPARK-57787). O wrapper de compatibilidade SQLContext do PySpark também funciona com o Spark Connect (SPARK-57021).

O driver JDBC do Spark Connect adiciona suporte a resultados ARRAY, MAP e STRUCT e um tratamento mais rico de conjuntos de resultados (SPARK-57380, SPARK-57274), metadados de tipo SQL e introspecção de esquema mais compatível (SPARK-57627) e tratamento aprimorado de exceções (SPARK-57933, SPARK-58619). A cobertura da API é expandida com DataFrame.zip, SCD Type 2 Auto CDC e tipos e literais de carimbo de data/hora (timestamp) em nanossegundos (SPARK-57247, SPARK-58247, SPARK-57160, SPARK-57161).

Separadamente, o trabalho da comunidade inclui o Spark Connect Gateway (SPARK-58455) para roteamento consciente de sessão e operação multilocatário, clientes Rust e Python baseados em Rust (SPARK-58960) para outro caminho de implementação de cliente, e uma proposta de descoberta de recursos (SPARK-56398) para identificar operações de servidor suportadas antes de enviar uma consulta. Esses esforços têm cronogramas de desenvolvimento separados e não vêm empacotados como recursos do 4.3.

PySpark: APIs mais ricas e melhor execução em Python

Os fluxos de trabalho em Python frequentemente criam colunas derivadas em etapas separadas, combinam os resultados e movem dados entre pandas, Arrow e Spark. O Spark 4.3 disponibiliza mais desse trabalho por meio das APIs de DataFrame, aprimorando os caminhos de execução subjacentes. DataFrame.zip adiciona uma maneira de combinar projeções de colunas compatíveis sem recorrer às APIs de RDD, inclusive ao usar o Spark Connect (SPARK-55886, SPARK-57247).

Exemplo: Combine identificadores com um valor derivado. Crie duas projeções a partir da mesma entrada e junte suas colunas:

O resultado emparelha id=1 com doubled=20 e id=2 com doubled=40. O `zip` combina transformações baseadas apenas em projeção do mesmo plano subjacente; filtragem, ordenação, junções (joins) ou agregações abaixo dessas projeções devem ser idênticas em ambos os lados para preservar o alinhamento das linhas.

O trabalho de execução mais amplo tem como alvo a transferência de dados, a criação de lotes e a computação nativa. Os lotes de entrada de UDF baseados em Pickle podem ser limitados por bytes em vez de apenas pela contagem de linhas, proporcionando melhor controle quando as linhas variam de tamanho (SPARK-57593). Projeções de pandas-on-Spark em lotes e implementações nativas adicionais do NumPy reduzem o trabalho evitável (SPARK-58230, SPARK-58234), enquanto a conversão de pandas para Spark adiciona suporte a colunas PyArrow ChunkedArray (SPARK-46776).

A versão também adiciona vinculações em Python e Scala para funções vetoriais existentes (SPARK-57284), covariância agrupada e estatísticas descritivas (SPARK-40336, SPARK-40337), operações de mediana móvel/expansiva e de erro padrão (SPARK-40341, SPARK-40340) e diagnósticos com show_versions (SPARK-40373). As variáveis locais de rastreamento (traceback) exigem consentimento explícito porque podem conter dados sensíveis (SPARK-57271).

Spark SQL: Prepare um contexto melhor para análises e IA

Os payloads de eventos chegam como documentos aninhados, e eventos próximos uns dos outros podem exigir mais precisão do que microssegundos. A preparação dessas entradas não deve exigir uma camada de processamento personalizada separada para cada transformação. O Spark 4.3 expande o SQL nativo para dados semiestruturados e análise temporal, incluindo manipulação de documentos, correspondência temporal e uma prévia opcional de carimbo de data/hora em nanossegundos (SPARK-56822).

Exemplo: Distinga dois eventos dentro do mesmo microssegundo. Ative a prévia (recurso ainda não estável, alterações que quebram a compatibilidade podem ocorrer) e compare os carimbos de data/hora separados por um nanossegundo (SPARK-56969, SPARK-56965, SPARK-57211):

A comparação é avaliada como true: o dígito final é preservado em vez de descartado. A prévia oferece suporte a TIMESTAMP_NTZ(p) e TIMESTAMP_LTZ(p) em precisões de 7 a 9.

Isso exigiu mais do que apenas aceitar um novo nome de tipo SQL. O suporte a nanossegundos se estende por análise sintática (parsing), representações de valores internos, conversões (casts), expressões, Spark Connect, cache e integração de fontes de dados (SPARK-56822). As novas funções timestamp_nanos e unix_nanos lidam com conversões numéricas (SPARK-57526, SPARK-57527). O suporte a armazenamento e conectores permanece específico para cada caminho de dados, portanto, a prévia deve ser avaliada de ponta a ponta.

Transforme payloads JSON variáveis em dados utilizáveis

Eventos de aplicativo, exportações de documentos e respostas de modelos geralmente chegam como JSON aninhado. O JSON_TABLE do Spark 4.3 (SPARK-58366) combina a expansão de arrays com a extração de campos tipados, enquanto as transformações de VARIANT permitem que os pipelines atualizem ou removam campos sem UDFs personalizadas de processamento de documentos (SPARK-57804, SPARK-57417). Juntos, eles simplificam a preparação de conteúdo para pipelines de análise, enriquecimento e recuperação.

Exemplo: Extrair seções relevantes de documentos.

Isso produz uma linha tipada que um pipeline pode enriquecer com metadados de origem antes de outras operações de downstream. O JSON_TABLE resolve seus caminhos de colunas por meio de uma travessia compartilhada de cada item da linha, evitando uma análise separada para cada coluna. Separadamente, o Spark estende o pushdown de extração de campos VARIANT para consultas suportadas que realizam agregações, ordenações ou junções. (SPARK-58089).

Trabalho futuro de SQL/JSON (SPARK-58686) estende essa direção com JSON_VALUE, JSON_EXISTS e JSON_QUERY para extração de escalares, verificações de presença e recuperação de fragmentos (SPARK-58685, SPARK-58687, SPARK-58723). O tratamento explícito de valores ausentes e erros ajudará os aplicativos a processar esquemas em alteração de forma mais previsível. Estes são desenvolvimentos futuros, não recursos adicionais da versão 4.3.

Vincule eventos às informações disponíveis no momento

A análise histórica e a avaliação de modelos precisam do contexto disponível quando um evento ocorreu, não de informações adicionadas posteriormente. O SQL ASOF JOIN do Spark 4.3 expressa (recurso em visualização, alterações incompatíveis podem ocorrer) essa correspondência temporal diretamente, substituindo junções de intervalo escritas manualmente seguidas de classificação (SPARK-58092).

Exemplo: Reconstruir os recursos disponíveis para uma predição. Aqui, available_at registra quando uma versão de recurso ficou disponível (SPARK-58122, SPARK-58123):

Uma predição às 10:03 corresponde à versão do recurso disponível às 10:00, não às 10:05. Um caminho de execução de sort-merge dedicado torna essa correspondência uma operação do motor, em vez de uma lógica de consulta específica do aplicativo. O resultado é um enriquecimento ponto no tempo mais simples para dados de treinamento, avaliações e análise de incidentes, desde que os carimbos de data/hora de disponibilidade representem com precisão o que era conhecido na época.

Melhorias Notáveis e Agradecimentos

O Spark 4.3 também introduz novas APIs e melhorias de desempenho para o processamento diário de dados. O SQL ganha ANSI UNNEST para expandir arrays em linhas, juntamente com a função de janela `counter_diff` para converter contadores cumulativos em deltas e `jaro_winkler_similarity` para comparações de similaridade de strings. Fontes de arquivos suportadas adicionam suporte opcional para leitura de arquivos tar, zip e 7z, eliminando uma etapa separada de extração. O motor melhora a execução de agregações e habilita a geração de código em estágio completo para operações UNION elegíveis por padrão. Uma otimização opcional distribui chaves de junção nulas entre partições de embaralhamento em junções externas e anti elegíveis. O processamento de dados aninhados ganha mais poda de campos não utilizados dentro de arrays de structs e geração de código para mais funções de ordem superior de array. Leituras vetorizadas de Parquet melhoram a conversão de tipos e a decodificação de dicionário.

O Spark 4.3 reflete a força da comunidade Apache Spark, com mais de 200 contribuidores ajudando a resolver mais de 1.100 tickets do Jira. Agradecemos a todos que contribuíram com código, revisões, testes, documentação e feedback para tornar este lançamento possível.

image1.png

Comece a Usar o Spark 4.3

Visite a página de downloads do Apache Spark para obter os downloads e a documentação do lançamento, e revise os guias de migração antes de atualizar. Para a disponibilidade no Databricks, consulte as notas de lançamento do Databricks Runtime.

(Esta publicação no blog foi traduzida utilizando ferramentas baseadas em inteligência artificial) Publicação original

Tags relacionadas:

Código aberto

Receba os posts mais recentes na sua caixa de entrada

Assine nosso blog e receba os posts mais recentes diretamente na sua caixa de entrada.