Separando Leitura e Escrita de Banco de Dados em Aplicações Rails API

A separação entre operações de leitura e escrita em bancos de dados é uma técnica essencial para otimizar aplicações Rails orientadas a API. Ao distribuir consultas entre servidores diferentes, é possível reduzir gargalos e melhorar a latência das respostas.

Fundamentos da Separação Leitura/Escrita

Em cenários onde as requisições de leitura superam as de escrita — comum em APIs RESTful —, redirecionar queries de leitura para réplicas do banco principal alivia a carga do servidor primário. Isso resulta em maior throughput e melhor aproveitamento dos recursos de hardware.

Configuração Inicial do Banco de Dados

O primeiro passo envolve ajustar o arquivo config/database.yml para definir conexões distintas para o servidor principal e a réplica:

production:
  primary_db:
    adapter: postgresql
    database: app_prod
    username: app_user
    password: <%= ENV['DB_MAIN_PASS'] %>
    host: db-main.exemplo.com
  replica_db:
    adapter: postgresql
    database: app_prod
    username: readonly_user
    password: <%= ENV['DB_REPLICA_PASS'] %>
    host: db-replica.exemplo.com
    replica: true

Vincualndo Modelos às Conexões

Com as conexões definidas, é preciso instruir o Active Record sobre qual banco usar para cada papel. Isso é feito na classe base dos modelos:

class ApplicationModel < ActiveRecord::Base
  self.abstract_class = true

  connects_to database: { writing: :primary_db, reading: :replica_db }
end

Automaticamente, o Rails passará a encaminhar operações de escrita (INSERT, UPDATE, DELETE) para o servidor primário e operações de leitura (SELECT) para a réplica.

Controle Manual de Conexões

Em situações específicas, pode ser necessário forçar o uso de um servidor particular. O método connected_to permite esse controle granular:

# Forçar leitura no banco primário para dados críticos
Account.connected_to(role: :writing) do
  Account.find_by(token: 'abc123')
end

# Utilizar réplica para listagens pesadas
Post.connected_to(role: :reading) do
  Post.where(published: true).limit(50)
end

Desafios Comuns

Latência de replicação: Réplicas podem ter um atraso na sincronização. Para dados sensíveis, leia diretamente do primário ou implemente verificações de consistência.

Indisponibilidade da réplica: É recomendável implementar mecanismos de fallback que redirecionem leituras para o banco principal caso a réplica esteja inacessível, evitando interrupções no serviço.

Tags: Ruby on Rails ActiveRecord postgresql Database Replication API Performance

Publicado em 7-18 20:56