Mirroring entre datacenters com MirrorMaker — Parte I

iundarigun
Dev Cave
Published in
6 min readMay 6, 2020

Há um tempo que estou querendo falar de Kafka, começando pelo básico e indo evoluindo os conteúdos. Por diversos motivos, estou trazendo um assunto um pouco mais avançado já de cara. Mas, deixo aqui um artigo para iniciar no Kafka bem legal do Guilherme Lodi. Também tem bastante coisa no README do meu repositório.

Antes de falar e aprofundar sobre o MirrorMaker, vou explicar o porque se fez necessário usá-lo. Então se chegou querendo ler unicamente sobre MirrorMaker, pode ir diretamente a segunda parte do artigo.

Introdução

Quando cogitamos usar alguma ferramenta para duplicar os dados entre datacenters é porque nosso ambiente/sistema/infra já ficou com um tamanho considerável. Os motivos de ter 2+ datacenters podem ser diversos, desde ter uma certa resiliência, ter uma forma simples de recuperar o funcionamento após um desastre ou até por motivos geográficos exigidos por lei.

Em alguns casos, mesmo tendo 2+ datacenters, podemos tomar a decisão de deixar alguns componentes centralizados num datacenter. Pensem por exemplo no banco de dados: dificilmente desenhamos inicialmente nossa aplicação para rodar em dois datacenters com um banco de dados em cada um, embora eventualmente vamos pensar em soluções para evitar pontos de falha única.

Pensando em Kafka, se vamos produzir e consumir eventos desde/para nossas aplicações talvez faça sentido tentar evitar ao máximo produzir ou consumir eventos através da internet. Se vocês estudaram sobre sistemas distribuídos, com certeza escutaram falar das 8 falacias da computação distribuída. Muitas delas fazem referência à problemas que podem vir acontecer facilmente fazendo cross-datacenters.

Arquiteturas

Existem vários tipos de arquitetura para trabalhar com Kafka quando pensamos em múltiplos datacenters.

  • Hub-and-Spokes: Um cluster de Kafka é o líder e os demais são os seguidores. A duplicação de dados acontece dos seguidores para o líder. Aplicações nos datacenters local processam as informações geradas desde aquele datacenter, enquanto as aplicações que precisam todos os dados, consomem os dados do cluster de Kafka do datacenter líder, preferivelmente deployada no mesmo datacenter.
  • Active-Active: Os clusters de Kafka precisam ter dados de todos os outros clusters de outros datacenters para disponibilizar para as aplicações que rodam no mesmo datacenter. Este modelo oferece redundância e resiliência mas, claro, traz outros problemas a considerar, como avaliar o impacto de consumir duas vezes a mesma mensagem em datacenters diferentes.
  • Active-Standby: Este tipo de arquitetura é usada para cenários de desastre. Se o datacenter principal morrer, o segundo datacenter é ativado e passa a funcionar pois tem todos os dados duplicados.
  • Strech Clusters: Uma opção que poderíamos achar interessante é montar um cluster Kafka com brokers distribuídos entre os diferentes DCs, com fatores de replicação de partitions configurados entre datacenters. Desta forma não precisaríamos efetivamente duplicar os dados. Esta configuração é totalmente desaconselhada, por vários motivos, relacionados à latência de rede e limitação de banda.

Para mais informações sobre caraterísticas de cada arquitetura, podem ver no README do meu repositório.

Descrevendo nosso problema

Qual é o nosso cenário? Antes de aplicar qualquer solução precisamos entender exatamente o problema que queremos resolver. No nosso caso, queremos que os datacenters atuem de forma totalmente independente. Isso significa que o que “entrar” por um datacenter deve ser processado pelo mesmo datacenter até a saída.

No nosso caso de uso, precisamos fazer uns ajuste para isso funcionar: Uma parte da nossa operação depende de um callback de terceiro, e esse callback pode voltar por qualquer dos datacenters. Quando esse callback chega, produzimos uma mensagem no Kafka. E é neste momento que se faz necessário duplicar dados, pois na hora de consumir, só podemos processar a mensagem se o processo foi iniciado por aquele datacenter. Pensando nas arquiteturas mencionadas acima, encaixamos estes tópicos específicos na categoria de Active-Active.

Soluções

Analisamos algumas ferramentas para fazer a duplicação. Sempre podemos fazer uma ferramenta própria caso necessário, mas há um bom número de corner cases que não queremos pensar (garantia de entrega, problemas de rede, latência, retentativas, etc).

MirrorMaker

É a solução que oficial do Kafka. A ideia é bem simples: O MirrorMaker usa o consumer padrão do Kafka, pega as mensagens e publica usando o producer padrão do Kafka no mesmo tópico no cluster de destino. Cada “instância” do MirrorMaker só tem um producer, mas pode ter vários consumers.

As principais caraterísticas são:

  • Recebe um parâmetro que é um pattern indicando quais tópicos precisam ter os dados duplicados no outro datacenter.
  • A duplicação acontecer Cluster to Cluster, isso é, consume de um único cluster e produz para um único cluster também. Se precisar duplicar entre mais clusters, vai precisar instâncias do MirrorMaker para cada par de clusters.
  • Como a duplicação acontece no mesmo nome de tópico, numa configuração Active-Active é preciso ter cuidado para evitar a duplicação cíclica, onde o tópico X é replicado do cluster A para o B e do B para o A, pois o consumer não distingue se o evento vem de um DC ou de outro.
  • Simples de escalar, pois podemos iniciar vários processos de MirrorMaker para o mesmo ou diferentes tópicos.
  • Se o tópico destino não existe, o mesmo é criado seguindo o padrão definido no cluster.

Como usar

$ <kafka-folder>/bin/kafka-mirror-maker.sh --consumer.config ./consumer.properties --producer.config ./producer.properties --new.consumer --num.streams=2 --whitelist "*"

Para ver mais detalhes sobre o MirrorMaker, pode ver na segunda parte do artigo.

uReplicator

O Uber fez uma solução usando o MirrorMaker como base. O motivo foi porque estavam enfrentando dois problemas:

  • O rebalancing dos consumers era demorado, resolvido em versões posteriores do MirrorMaker
  • Acrescentar novos tópicos precisava uma nova instância ou criar um pattern muito genérico.

Principais caraterísticas:

  • O setup é mais complexo, assim como os componentes envolvidos.
  • Usa o Apache Helix para coordenar os tópicos que serão replicados.
  • Para fazer a duplicação, usa o conceito de workers com a configuração do MirrorMaker
  • Adicionamos tópicos de forma dinâmica usando uma API

Como usar

Para facilitar o uso, podem usar o jar do uReplicator que deixei no meu repositório. Basicamente, é o build do projeto uReplicator opensource da Uber. Também pode usar os docker-compose do mesmo repositório para subir dois clusters básicos de Kafka.

Para rodar o uReplicator precisamos levantar do controller primeiro:

$ java -jar uReplicator.jar startMirrorMakerController -helixClusterName clusterHelix -zookeeper localhost:2182 -port 9000

O zookeeper será usado para controlar quais duplicações precisa fazer, usando o Apache Helix. A continuação vamos subir o worker:

$ java -jar uReplicator.jar startMirrorMakerWorker --consumer.config config/consumer.properties --producer.config config/producer.properties --helix.config config/helix.properties

O worker ficará “atrelado” ao controller levantado antes usando o Apache Helix. Por baixo do panos o worker usa o próprio MirrorMaker, por isso fornecemos os arquivos producer.properties e consumer.properties.

Para indicar que tópicos serão replicados, fazemos um POST no controller:

$ curl -X POST -d '{"topic":"*", "numPartitions":"14"}' http://localhost:9000/topics

Exploramos menos o uReplicator pela complexidade desnecessária no nosso cenário, então posso ter falado alguma besteira, e se for assim, peço desculpas :D

Confluent Replicator

É a ferramenta da Confluent. É uma ferramenta paga que pode ser usada como plugin dentro do Kafka Connect e não chegamos a testar ela. Foi desenvolvida tentando resolver dois problemas não atendidos pelo MirrorMaker:

  • Replica de configuração de tópico, interessante em datacenter de desastre, pois pode dar problemas se os tópicos tem configurações diferentes (retenção, partitions, etc).
  • Possibilidade de replicar o tópico para vários clusters simultaneamente

MirrorMaker 2

Recentemente, na versão 2.4 do Kafka, foi incluída uma nova versão do MirrorMaker. Exploramos muito pouco a ferramenta, pois quando descobrimos ela, já tínhamos avançado bastante no MirrorMaker original. A sensação é que resolve alguns cenários não atendidos na primeira versão, mas a complexidade de uso também aumenta. Para mais informações, pode ver a documentação oficial no confluence da apache.

Conclusão

Neste primeiro post, não quis aprofundar em nada técnico e sim explicar os motivos de procurar uma ferramenta para fazer a duplicação de dados, assim como algumas alternativas que analisamos.

Só a nível de curiosidade, até aqui evitei usar a palavra “replicação” de dados aplicado no cenário apresentado, apostando por usar “duplicação”. O motivo é que no ambiente de Kafka, o processo de replicação é atrelado à replicação de dados das partitions entre brokers dentro do mesmo cluster. A palavra usada para essa “duplicação” é mirroring, mas achei que espelhamento ficaria estranha e literal demais.

No segundo artigo, vou aprofundar no MirrorMaker e algumas poucas configurações avançadas.

Referências

--

--

iundarigun
Dev Cave

Java and Kotlin software engineer at Clearpay