Todos os produtos
Search
Central de documentação

ApsaraDB for MongoDB:Use ApsaraDB for MongoDB to store logs

Última atualização: Jun 26, 2026

Serviços online geram grandes volumes de logs operacionais e de acesso. O armazenamento em texto simples funciona para consultas rápidas, mas falha ao filtrar, agregar e extrair insights de dados massivos. Este tópico descreve como usar o ApsaraDB for MongoDB para armazenar e analisar logs de acesso de servidores web. Os mesmos padrões aplicam-se a outros tipos de log.

Estruture dados de log para o MongoDB

A estrutura dos documentos de log afeta diretamente o desempenho das consultas e o custo de armazenamento. Esta seção apresenta três abordagens, da mais simples à mais eficiente.

Uma entrada típica de log de acesso de servidor web tem o seguinte formato:

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"
            

Ela registra a source da requisição, nome de usuário, URL do recurso, código de resposta, sistema operacional e navegador.

Armazene a linha bruta

A abordagem mais simples armazena cada entrada de log como um único campo de string:

{
            _id: ObjectId('4f442120eb03305789000000'),
            line: '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "[http://www.example.com/start.html](http://www.example.com/start.html)" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
            }
            

Essa estratégia funciona, mas dificulta as consultas. Como o ApsaraDB for MongoDB não é um mecanismo de análise de texto, filtrar ou agregar strings de log brutas torna-se complexo.

Analise os dados em campos estruturados

Antes da inserção, analise cada linha de log e separe-a em campos distintos:

{
            _id: ObjectId('4f442120eb03305789000000'),
            host: "127.0.0.1",
            logname: null,
            user: 'frank',
            time: ISODate("2000-10-10T20:55:36Z"),
            path: "/apache_pb.gif",
            request: "GET /apache_pb.gif HTTP/1.0",
            status: 200,
            response_size: 2326,
            referrer: "[http://www.example.com/start.html](http://www.example.com/start.html)",
            user_agent: "Mozilla/4.08 [en] (Win98; I ;Nav)"
            }
            

Campos estruturados permitem filtrar e indexar valores específicos, oferecendo vantagem significativa sobre o armazenamento de linhas brutas.

Remova campos não utilizados

Documentos grandes prejudicam o desempenho e aumentam custos. Descarte campos desnecessários para consulta. Neste exemplo, user, request e status raramente são necessários para análise. O ObjectId _id já codifica o horário de inserção, permitindo também a remoção de time — embora mantê-lo simplifique consultas por intervalo de tempo. Um documento enxuto fica assim:

{
            _id: ObjectId('4f442120eb03305789000000'),
            host: "127.0.0.1",
            time: ISODate("2000-10-10T20:55:36Z"),
            path: "/apache_pb.gif",
            referer: "[http://www.example.com/start.html](http://www.example.com/start.html)",
            user_agent: "Mozilla/4.08 [en] (Win98; I ;Nav)"
            }
            

Sempre que possível, utilize tipos de dados compactos. Por exemplo, armazene códigos de status HTTP como inteiros em vez de strings.

Grave logs no ApsaraDB for MongoDB

Pipelines de log frequentemente precisam sustentar alto throughput de escrita. Controle o compromisso entre durabilidade e desempenho definindo um write concern em cada inserção:

db.events.insert({
                host: "127.0.0.1",
                time: ISODate("2000-10-10T20:55:36Z"),
                path: "/apache_pb.gif",
                referer: "[http://www.example.com/start.html](http://www.example.com/start.html)",
                user_agent: "Mozilla/4.08 [en] (Win98; I ;Nav)"
                },
                {
                 writeConcern:{w: 0} 
                }
                )
Nota
  • Para obter o máximo throughput de escrita, defina o write concern como {w: 0}.

  • Para logs com informações sensíveis ou relacionadas a faturamento, defina o write concern como {w: 1} ou {w: "majority"} para garantir a durabilidade.

Para reduzir idas e vindas na rede, agrupe vários documentos de log em uma única inserção:

db.events.insert([doc1, doc2, ...])

Consulte logs no ApsaraDB for MongoDB

Com os campos estruturados configurados, execute consultas direcionadas na coleção.

  • Consulte todas as requisições para um caminho específico: q_events = db.events.find({'path': '/apache_pb.gif'})

    Nota

    Se essa consulta for frequente, crie um índice no campo path: db.events.createIndex({path: 1}).

  • Consulte todas as requisições dentro de um intervalo de tempo:

    q_events = db.events.find({'time': { '$gte': ISODate("2016-12-19T00:00:00.00Z"),'$lt': ISODate("2016-12-20T00:00:00.00Z")}})
    Nota

    Crie um índice no campo time para acelerar consultas por intervalo de tempo: db.events.createIndex({time: 1}).

  • Consulte todas as requisições de um host específico dentro de um intervalo de tempo:

    q_events = db.events.find({
                    'host': '127.0.0.1',
                    'time': {'$gte': ISODate("2016-12-19T00:00:00.00Z"),'$lt': ISODate("2016-12-20T00:00:00.00Z" }
                    })
                        

    Para análises mais complexas — agrupamento, contagem ou cálculo de agregações — utilize o pipeline de agregação ou o framework MapReduce. Indexe os campos usados para filtragem ou ordenação para manter a latência das consultas baixa.

Sharding de dados

À medida que o volume de logs cresce, a capacidade de escrita e armazenamento de um único nó torna-se um gargalo. Aplique shard na coleção para distribuir os dados entre vários nós. A escolha da chave de shard afeta diretamente o throughput de escrita e o desempenho das consultas.

  • Chave de shard baseada em timestamp (por exemplo, _id ou time): Como os timestamps aumentam monotonicamente, todas as novas inserções de log vão para o mesmo shard. Isso cria um ponto crítico de escrita e faz com que consultas de dados recentes atinjam apenas um ou dois shards, em vez de distribuir a carga pelo cluster.

    • Novos dados de log concentram-se em um único shard, impedindo que o throughput de escrita escale junto com o cluster.

    • Consultas por logs recentes atingem apenas alguns shards, deixando a capacidade total de consulta do cluster subutilizada.

  • Sharding com hash: Utiliza _id como chave de shard padrão. O hash distribui as inserções uniformemente entre todos os shards, permitindo que o throughput de escrita escale linearmente com o número de shards. A contrapartida é que consultas por intervalo — comuns na análise de logs — precisam ser dispersas por todos os shards e ter seus resultados mesclados, o que aumenta a latência.

  • Sharding por intervalo em um campo bem distribuído: Se um campo como path possui muitos valores distintos e uniformemente distribuídos, sendo frequentemente usado em consultas, ele serve como uma boa chave de shard. Benefícios:

    • Requisições de escrita espalham-se uniformemente pelos shards.

    • Consultas por intervalo em path atingem um número reduzido de shards, melhorando a eficiência.

    As desvantagens incluem:

    • Um valor de path com alta frequência concentra seus documentos em um único chunk ou shard, criando um ponto crítico.

    • Um campo path com baixa cardinalidade resulta em distribuição desigual dos dados.

    Para resolver tanto os pontos críticos quanto a baixa cardinalidade, adicione um campo secundário à chave de shard. Por exemplo, estenda {path: 1} para {path: 1, ssk: 1}.

    Atribua um valor aleatório a ssk — como o hash de _id — para espalhar caminhos populares entre os shards. Alternativamente, use um timestamp para que documentos com o mesmo path sejam ordenados cronologicamente dentro de cada shard.

    A chave composta evita que qualquer valor isolado de chave de shard domine a distribuição, equilibrando throughput de escrita e localidade de consulta. Cada estratégia de sharding tem seus compromissos; escolha com base nos seus padrões de acesso e trajetória de crescimento.

Gerencie o crescimento dos dados

Dados de log acumulam-se rapidamente, mas seu valor diminui com o tempo. Dados de três meses atrás raramente impactam a análise atual, contudo ainda consomem armazenamento e aumentam custos. O ApsaraDB for MongoDB oferece três abordagens para gerenciar o ciclo de vida dos dados.

  • Índices TTL (Time To Live): Um índice TTL é um índice de campo único que remove automaticamente documentos após um período especificado. Para expirar entradas de log 30 horas após o horário da requisição, execute: db.events.createIndex( { time: 1 }, { expireAfterSeconds: 108000 } ).

    Nota

    A tarefa em segundo plano que exclui documentos expirados executa a cada 60 segundos e utiliza thread única. Sob altas cargas de escrita, documentos expirados podem acumular-se mais rápido do que a tarefa consegue removê-los, consumindo temporariamente armazenamento extra.

  • Coleções limitadas (Capped collections): Para limitar o espaço de armazenamento em vez de impor expiração baseada em tempo, utilize uma coleção limitada. Quando a coleção atinge seu tamanho configurado ou limite de documentos, o MongoDB remove automaticamente os documentos mais antigos. Exemplo: db.createCollection("event", {capped: true, size: 104857600000}.

  • Arquivamento periódico por coleção: Ao final de cada mês, renomeie a coleção atual e crie uma nova para o mês seguinte. Inclua o ano e o mês no nome da coleção:

    events-201601
                    events-201602
                    events-201603
                    events-201604
                    ....
                    events-201612
                        

    Para purgar os dados de um mês, exclua a coleção correspondente:

     db["events-201601"].drop()
                    db["events-201602"].drop()
                        

    A contrapartida dessa abordagem é que consultas abrangendo múltiplos meses tornam-se mais complexas, pois os resultados precisam ser mesclados a partir de várias coleções.