Perguntas de Entrevista sobre Redes Distribuidas: CAP, Consenso e Design de Sistemas (2026)

Redes distribuidas sao fundamentais para sistemas modernos - desde microsservicos ate blockchain e CDNs globais. Compreender esses conceitos e crucial para cargos de engenharia senior. Este guia aborda as perguntas mais comuns em entrevistas com respostas detalhadas e exemplos praticos.

Fundamentos

1. O que e um sistema distribuido?

Resposta: Um sistema distribuido e uma colecao de computadores independentes que aparentam para os usuarios como um unico sistema coerente. Caracteristicas principais:

  • Concorrencia: Componentes executam simultaneamente
  • Sem relogio global: Nos possuem relogios independentes
  • Falhas independentes: Componentes podem falhar sem afetar outros
  • Troca de mensagens: Comunicacao via mensagens de rede

Exemplos: Google Search, streaming da Netflix, rede Bitcoin.

2. Explique o teorema CAP

Resposta: O teorema CAP afirma que um sistema distribuido so pode garantir duas de tres propriedades:

  • Consistencia: Todos os nos veem os mesmos dados ao mesmo tempo
  • Disponibilidade: Toda requisicao recebe uma resposta
  • Tolerancia a particao: Sistema continua operando apesar de falhas de rede

Na pratica, tolerancia a particao e necessaria (redes falham), entao voce escolhe entre CP (consistencia) ou AP (disponibilidade):

CP Systems: MongoDB, HBase, Redis Cluster
- Sacrifice availability during partitions
- Strong consistency guarantees

AP Systems: Cassandra, DynamoDB, CouchDB
- Remain available during partitions
- Eventually consistent

3. O que e consistencia eventual?

Resposta: Consistencia eventual garante que se nenhuma nova atualizacao for feita, todas as replicas eventualmente convergirao para o mesmo valor. E uma garantia mais fraca do que consistencia forte, mas permite maior disponibilidade.

// Example: DNS propagation
// Update takes time to propagate globally
// Different users may see different values temporarily
// Eventually, all DNS servers have the same record

// Conflict resolution strategies:
// 1. Last-write-wins (LWW) - timestamp-based
// 2. Vector clocks - track causality
// 3. CRDTs - mathematically guaranteed convergence

4. Explique a diferenca entre escalabilidade horizontal e vertical

Resposta:

AspectoEscalabilidade VerticalEscalabilidade Horizontal
MetodoAdicionar recursos a uma maquinaAdicionar mais maquinas
CustoCaro em escalaHardware comum
LimiteTeto de hardwareTeoricamente ilimitado
ComplexidadeSimplesRequer logica de distribuicao
Tempo de inatividadeGeralmente necessarioZero tempo de inatividade possivel

Consenso e Coordenacao

5. O que e o algoritmo de consenso Raft?

Resposta: Raft e um algoritmo de consenso para gerenciar um log replicado. Foi projetado para ser compreensivel (diferente do Paxos). Componentes principais:

  • Eleicao de lider: Um no e eleito lider, processa todas as requisicoes de clientes
  • Replicacao de log: Lider replica entradas para seguidores
  • Seguranca: Apenas nos com logs atualizados podem se tornar lider
Raft states:
1. Follower - Default state, responds to leader
2. Candidate - Requesting votes for leadership
3. Leader - Handles all client requests

Election process:
1. Follower timeout expires
2. Becomes candidate, increments term
3. Requests votes from peers
4. Majority votes = new leader
5. Sends heartbeats to maintain leadership

6. O que e um lock distribuido?

Resposta: Um lock distribuido garante que apenas um processo em multiplos nos pode acessar um recurso. Desafios de implementacao:

// Redis distributed lock (Redlock algorithm)
const Redis = require('ioredis');

async function acquireLock(redis, key, ttl) {
  const token = crypto.randomUUID();
  const result = await redis.set(key, token, 'NX', 'PX', ttl);
  return result === 'OK' ? token : null;
}

async function releaseLock(redis, key, token) {
  // Lua script for atomic check-and-delete
  const script = `
    if redis.call("get", KEYS[1]) == ARGV[1] then
      return redis.call("del", KEYS[1])
    else
      return 0
    end
  `;
  return redis.eval(script, 1, key, token);
}

// Usage
const token = await acquireLock(redis, 'my-resource', 30000);
if (token) {
  try {
    // Critical section
  } finally {
    await releaseLock(redis, 'my-resource', token);
  }
}

7. Explique relogios vetoriais

Resposta: Relogios vetoriais rastreiam causalidade entre eventos em sistemas distribuidos. Cada no mantem um vetor de timestamps logicos:

// Vector clock example with 3 nodes
// Initial: [0, 0, 0]

// Node A sends message: [1, 0, 0]
// Node B receives and sends: [1, 1, 0]
// Node C receives: [1, 1, 1]

// Comparison rules:
// V1 < V2 if all V1[i] <= V2[i] and at least one V1[i] < V2[i]
// V1 || V2 (concurrent) if neither V1 < V2 nor V2 < V1

class VectorClock {
  constructor(nodeId, numNodes) {
    this.nodeId = nodeId;
    this.clock = new Array(numNodes).fill(0);
  }

  increment() {
    this.clock[this.nodeId]++;
    return [...this.clock];
  }

  update(received) {
    for (let i = 0; i < this.clock.length; i++) {
      this.clock[i] = Math.max(this.clock[i], received[i]);
    }
    this.clock[this.nodeId]++;
  }

  compare(other) {
    let less = false, greater = false;
    for (let i = 0; i < this.clock.length; i++) {
      if (this.clock[i] < other[i]) less = true;
      if (this.clock[i] > other[i]) greater = true;
    }
    if (less && !greater) return -1; // this happened before
    if (greater && !less) return 1;  // other happened before
    return 0; // concurrent
  }
}

Protocolos de Rede

8. Compare TCP vs UDP para sistemas distribuidos

Resposta:

CaracteristicaTCPUDP
ConexaoOrientado a conexaoSem conexao
ConfiabilidadeEntrega garantidaMelhor esforco
OrdenacaoOrdenadoSem ordenacao
VelocidadeMais lento (handshake)Mais rapido
Casos de usoHTTP, bancos de dadosDNS, streaming, jogos
// When to use each:
// TCP: When you need reliability
// - Database connections
// - File transfers
// - API calls

// UDP: When speed matters more than reliability
// - Real-time gaming
// - Video streaming
// - DNS queries
// - Health checks

9. O que e gRPC e quando voce usaria?

Resposta: gRPC e um framework RPC de alto desempenho usando Protocol Buffers e HTTP/2:

  • Protocolo binario: Payloads menores que JSON
  • Streaming: Suporte a streaming bidirecional
  • Geracao de codigo: Clientes/servidores type-safe
  • HTTP/2: Multiplexacao, compressao de headers
// user.proto
syntax = "proto3";

service UserService {
  rpc GetUser(GetUserRequest) returns (User);
  rpc ListUsers(ListUsersRequest) returns (stream User);
  rpc CreateUser(User) returns (User);
}

message User {
  string id = 1;
  string name = 2;
  string email = 3;
}

message GetUserRequest {
  string id = 1;
}

10. Explique a arquitetura de service mesh

Resposta: Um service mesh e uma camada de infraestrutura para comunicacao servico-a-servico. Componentes:

  • Plano de dados: Proxies sidecar (Envoy) gerenciam trafego
  • Plano de controle: Gerencia configuracao de proxies
# Istio example - traffic splitting
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-service
spec:
  hosts:
  - my-service
  http:
  - route:
    - destination:
        host: my-service
        subset: v1
      weight: 90
    - destination:
        host: my-service
        subset: v2
      weight: 10

Beneficios: mTLS, observabilidade, gerenciamento de trafego, retries sem alteracoes de codigo.

Tolerancia a Falhas

11. O que e o padrao circuit breaker?

Resposta: Circuit breaker previne falhas em cascata falhando rapidamente quando um servico esta indisponivel:

class CircuitBreaker {
  constructor(options) {
    this.failureThreshold = options.failureThreshold || 5;
    this.resetTimeout = options.resetTimeout || 30000;
    this.state = 'CLOSED';
    this.failures = 0;
    this.lastFailure = null;
  }

  async call(fn) {
    if (this.state === 'OPEN') {
      if (Date.now() - this.lastFailure > this.resetTimeout) {
        this.state = 'HALF_OPEN';
      } else {
        throw new Error('Circuit breaker is OPEN');
      }
    }

    try {
      const result = await fn();
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure();
      throw error;
    }
  }

  onSuccess() {
    this.failures = 0;
    this.state = 'CLOSED';
  }

  onFailure() {
    this.failures++;
    this.lastFailure = Date.now();
    if (this.failures >= this.failureThreshold) {
      this.state = 'OPEN';
    }
  }
}

12. Explique o padrao bulkhead

Resposta: Bulkhead isola componentes para que falhas nao se propaguem. Como compartimentos de navio:

// Thread pool bulkhead
const criticalPool = new ThreadPool({ size: 10 });
const nonCriticalPool = new ThreadPool({ size: 5 });

// If non-critical service exhausts its pool,
// critical operations still have dedicated resources

// Semaphore bulkhead
class Bulkhead {
  constructor(maxConcurrent) {
    this.maxConcurrent = maxConcurrent;
    this.current = 0;
    this.queue = [];
  }

  async execute(fn) {
    if (this.current >= this.maxConcurrent) {
      throw new Error('Bulkhead full');
    }

    this.current++;
    try {
      return await fn();
    } finally {
      this.current--;
    }
  }
}

13. O que e tolerancia a falhas bizantinas?

Resposta: BFT lida com nos que se comportam de forma arbitraria (maliciosamente ou devido a bugs). O Problema dos Generais Bizantinos:

  • Requer 3f+1 nos para tolerar f falhas bizantinas
  • Usado em blockchain (PBFT, Tendermint)
  • Mais caro que tolerancia a falhas por crash
PBFT phases:
1. Pre-prepare: Leader proposes value
2. Prepare: Nodes broadcast prepared messages
3. Commit: Nodes commit after 2f+1 prepares
4. Reply: Send result to client

Requires 2f+1 matching messages at each phase

Balanceamento de Carga e Roteamento

14. Compare algoritmos de balanceamento de carga

Resposta:

// Round Robin - Simple rotation
class RoundRobin {
  constructor(servers) {
    this.servers = servers;
    this.current = 0;
  }

  next() {
    const server = this.servers[this.current];
    this.current = (this.current + 1) % this.servers.length;
    return server;
  }
}

// Weighted Round Robin - Based on capacity
class WeightedRoundRobin {
  constructor(servers) {
    // servers: [{ host: 'a', weight: 3 }, { host: 'b', weight: 1 }]
    this.servers = [];
    for (const s of servers) {
      for (let i = 0; i < s.weight; i++) {
        this.servers.push(s.host);
      }
    }
    this.current = 0;
  }
}

// Least Connections - Route to least busy
class LeastConnections {
  constructor(servers) {
    this.connections = new Map(servers.map(s => [s, 0]));
  }

  next() {
    let min = Infinity, selected;
    for (const [server, count] of this.connections) {
      if (count < min) {
        min = count;
        selected = server;
      }
    }
    return selected;
  }
}

// Consistent Hashing - For caches/sharding
// Minimizes redistribution when nodes change

15. Explique hashing consistente

Resposta: Hashing consistente distribui dados entre nos minimizando redistribuicao quando nos sao adicionados/removidos:

const crypto = require('crypto');

class ConsistentHash {
  constructor(replicas = 100) {
    this.replicas = replicas;
    this.ring = new Map();
    this.sortedKeys = [];
  }

  hash(key) {
    return crypto.createHash('md5')
      .update(key)
      .digest('hex')
      .substring(0, 8);
  }

  addNode(node) {
    for (let i = 0; i < this.replicas; i++) {
      const hash = this.hash(`${node}:${i}`);
      this.ring.set(hash, node);
      this.sortedKeys.push(hash);
    }
    this.sortedKeys.sort();
  }

  removeNode(node) {
    for (let i = 0; i < this.replicas; i++) {
      const hash = this.hash(`${node}:${i}`);
      this.ring.delete(hash);
      this.sortedKeys = this.sortedKeys.filter(k => k !== hash);
    }
  }

  getNode(key) {
    const hash = this.hash(key);
    for (const nodeHash of this.sortedKeys) {
      if (hash <= nodeHash) {
        return this.ring.get(nodeHash);
      }
    }
    return this.ring.get(this.sortedKeys[0]);
  }
}

Mensageria e Filas

16. Compare padroes de filas de mensagens

Resposta:

  • Ponto-a-ponto: Um produtor, um consumidor (filas de tarefas)
  • Pub/sub: Um produtor, multiplos consumidores (broadcast de eventos)
  • Requisicao/resposta: Padrao de mensageria sincrona
Delivery guarantees:
- At most once: May lose messages (fastest)
- At least once: May duplicate (requires idempotency)
- Exactly once: Most complex, often needs transactions

Technologies:
- RabbitMQ: Traditional message broker, AMQP
- Kafka: Distributed log, high throughput
- Redis Streams: Simple, built into Redis
- AWS SQS: Managed, scalable

17. O que e o padrao outbox?

Resposta: O padrao outbox garante publicacao confiavel de mensagens com transacoes de banco de dados:

// Instead of:
await db.transaction(async (tx) => {
  await tx.insert('orders', order);
  await messageQueue.publish('order.created', order); // Can fail!
});

// Use outbox pattern:
await db.transaction(async (tx) => {
  await tx.insert('orders', order);
  await tx.insert('outbox', {
    event_type: 'order.created',
    payload: JSON.stringify(order),
    created_at: new Date()
  });
});

// Separate process polls outbox and publishes
async function processOutbox() {
  const events = await db.query(
    'SELECT * FROM outbox WHERE processed = false LIMIT 100'
  );

  for (const event of events) {
    await messageQueue.publish(event.event_type, event.payload);
    await db.update('outbox', { id: event.id }, { processed: true });
  }
}

Observabilidade

18. O que e rastreamento distribuido?

Resposta: Rastreamento distribuido acompanha requisicoes atraves das fronteiras de servicos:

// OpenTelemetry example
const { trace } = require('@opentelemetry/api');

const tracer = trace.getTracer('my-service');

async function handleRequest(req) {
  const span = tracer.startSpan('handleRequest');

  try {
    span.setAttribute('user.id', req.userId);

    // Child span for database call
    const dbSpan = tracer.startSpan('database.query', {
      parent: span
    });
    const result = await db.query('...');
    dbSpan.end();

    return result;
  } catch (error) {
    span.recordException(error);
    span.setStatus({ code: SpanStatusCode.ERROR });
    throw error;
  } finally {
    span.end();
  }
}

// Trace context propagation
// W3C Trace Context header: traceparent
// Format: version-trace_id-span_id-flags
// Example: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01

19. Explique os tres pilares da observabilidade

Resposta:

  • Logs: Eventos discretos com contexto
  • Metricas: Medicoes numericas ao longo do tempo
  • Traces: Fluxo de requisicoes entre servicos
Logs: What happened?
- Structured JSON logs
- Correlation IDs
- Log levels (debug, info, warn, error)

Metrics: How is the system performing?
- Counters: request_count
- Gauges: active_connections
- Histograms: request_duration

Traces: Where did the request go?
- Spans with timing
- Parent-child relationships
- Cross-service context

Seguranca

20. Como voce protege a comunicacao servico-a-servico?

Resposta:

  • mTLS: Autenticacao TLS mutua
  • Service mesh: mTLS automatico (Istio, Linkerd)
  • Chaves de API: Simples mas menos seguro
  • JWT: Autenticacao stateless
# Istio PeerAuthentication for mTLS
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: my-namespace
spec:
  mtls:
    mode: STRICT

Questoes de Design de Sistemas

21. Projete um limitador de taxa distribuido

Resposta:

// Token bucket with Redis
class DistributedRateLimiter {
  constructor(redis, options) {
    this.redis = redis;
    this.capacity = options.capacity;
    this.refillRate = options.refillRate; // tokens per second
  }

  async isAllowed(key) {
    const now = Date.now();
    const script = `
      local key = KEYS[1]
      local capacity = tonumber(ARGV[1])
      local refillRate = tonumber(ARGV[2])
      local now = tonumber(ARGV[3])

      local bucket = redis.call('HMGET', key, 'tokens', 'lastRefill')
      local tokens = tonumber(bucket[1]) or capacity
      local lastRefill = tonumber(bucket[2]) or now

      -- Refill tokens
      local elapsed = (now - lastRefill) / 1000
      tokens = math.min(capacity, tokens + elapsed * refillRate)

      if tokens >= 1 then
        tokens = tokens - 1
        redis.call('HMSET', key, 'tokens', tokens, 'lastRefill', now)
        redis.call('EXPIRE', key, 60)
        return 1
      else
        return 0
      end
    `;

    return await this.redis.eval(script, 1, key,
      this.capacity, this.refillRate, now);
  }
}

22. Como voce projetaria um cache distribuido?

Resposta: Consideracoes principais:

  • Particionamento: Hashing consistente entre nos
  • Replicacao: Primario-replica para tolerancia a falhas
  • Expulsao: Baseado em LRU, LFU ou TTL
  • Consistencia: Write-through, write-behind ou cache-aside
Cache-aside pattern:
1. Check cache
2. If miss, read from database
3. Update cache
4. Return data

Write-through pattern:
1. Write to cache
2. Cache writes to database
3. Ensures consistency but adds latency

Write-behind pattern:
1. Write to cache
2. Cache async writes to database
3. Better performance, eventual consistency

Conclusao

Sistemas distribuidos sao complexos, mas entender esses conceitos fundamentais - consenso, tolerancia a falhas, redes e observabilidade - preparara voce para entrevistas de engenharia senior. Foque em trade-offs: raramente existe uma solucao perfeita, apenas trade-offs apropriados para requisitos especificos.