MongoDB e dados flexíveis
(Secção Tecnologia e Infraestrutura)
Resumo breve
MongoDB - Armazenamento focado em documentário com esquemas flexíveis (BSON), inserções rápidas, zoom horizontal e o poderoso Agregation Pipeline. Em iGaming, é perfeitamente adequado para perfis de jogadores, cartões CRM flexíveis, logs de eventos, telemetria, projeções materializadas a partir de striptease, catálogos de jogos e apresentações de frentes. Para invariantes em dinheiro (carteiras/ledger), o caminho SQL/COP é mais comum; É apropriado como read-model e armazenamento de documentação de alto desempenho.
Onde dá o máximo em
Perfis e configurações de jogadores: variáveis de estrutura (configurações locais, preferências, metadados KYC).
Diretórios de conteúdo/jogos/provedores: leitura rápida de cartões, filtros, marcas de formatação, texto completo.
Eventos/telemetria/revistas: TPS alto, janelas temporárias, armazenamento TTL.
Apresentações materializadas (CQRS): telas rápidas (liderbords, ações recentes, unidades).
Personalização/fichas ML online: pattern KV em coleções, TTL curto.
Princípios de esquema flexível: disciplina em vez de caos
Não é «sem esquema». O esquema vive em código e validação.
Recomendado:1. Esquema como contrato: JSON Schema Validation em coleções.
2. Versionagem de documentos com o campo 'schemaVersion'.
3. Campos obrigatórios rigorosos (id, chaves de busca), «cauda» de atributos raros - opcional.
4. Limite a dimensão de matrizes e anexos (para índices e RAM).
5. Migrações no fundo, updates por 'schemaVersion', shedoolers, back phils.
Exemplo: JSON Schema Validation
js db.createCollection("player_profiles", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["playerId", "createdAt", "schemaVersion"],
properties: {
playerId: { bsonType: "string" },
createdAt: { bsonType: "date" },
schemaVersion: { bsonType: "int", minimum: 1 },
locale: { bsonType: "string" },
kyc: {
bsonType: "object",
properties: {
status: { enum: ["pending", "verified", "rejected"] },
doc: { bsonType: "object" }
}
}
}
}
}
});
Modelo de dados e engenharia de documentos
Projete «sob consulta»: 1 tela/endpoint = 1 documento ou um pequeno conjunto de documentos.
Denormalização: inclua pequenas subconjunturas (por exemplo, mini-cartões de provedores de jogos).
- Incorporação: para fatias muito ligadas e raramente atualizadas.
- Links ('ref'): com grandes e frequentes updates/reutilização.
- Limite de tamanho: documento ≤ 16 MB; binários grandes - GridFS/armazenamento de objetos.
- Auditoria/metadados: « », « », « », « ».
Índices: qualidade de leitura e estabilidade latency
Tipos de índice e prática:- B-Tree (principal)
Compound: A ordem dos campos corresponde a frequentes pregados e ordens.
Regra Preferix: «(tenantId, playerId, createdAt)» funcionam as opções de prefixo.
Triagem: Leve em conta 'sort' no fim do índice (por exemplo, 'createdAt: -1').
js db.bets.createIndex(
{ tenantId: 1, playerId: 1, createdAt: -1 },
{ name: "idx_bets_tenant_player_created_desc" }
);
Partial / Sparse
Acelera subconjeitos frequentes ('status:' pending ') e reduz o tamanho.
js db.withdrawals.createIndex(
{ playerId: 1, createdAt: -1 },
{ partialFilterExpression: { status: "pending" } }
);
TTL
Para telemetria/logs/fitas temporárias - caducidade automática.
js db.events.createIndex({ expireAt: 1 }, { expireAfterSeconds: 0 });
Texto/autocomplete
'text' para o texto completo (restrições de linguagens); para o fim automático - 'n-gram '/trigram através de campos e abordagens regex ou Atlas Search.
Antipattern Índice
O índice para tudo → uma queda na velocidade de gravação.
Baixa cardinalidade sem partidal → baixa seletividade.
Compundos duplicados.
Indexar campos dentro de matrizes gigantes sem limites.
Agregation Pipeline: telas rápidas e relatórios
Use '$ match' → '$ sort' → '$ limit' como estágios iniciais; projetar índices sob '$ match/$ sort'.
'$ lookup' para joynos controlados (suaves, em quantidades razoáveis).
'$ facet' para várias métricas; '$unionWith' é uma combinação de coleções.
'$ merge '/' $ out' - materialização dos resultados na coleção (read-models).
js db.bets.aggregate([
{ $match: { tenantId: "eu-1", playerId: "p123" } },
{ $sort: { createdAt: -1 } },
{ $limit: 100 },
{ $group: {
_id: "$playerId",
lastBets: { $push: { amount: "$amount", ts: "$createdAt", game: "$gameId" } },
totalAmount: { $sum: "$amount" }
} }
]);
Transações, coerência e idempotação
O single-documento atomic é uma atômica gratuita; invariantes complexos - pense em dividir-se em documentos.
Multi-estiveram Transacções (ACID) - há com redes de réplica, mas mais caras em latency; usar de forma pontual.
- 'w:' majority 'para registros críticos (valor latency);
- 'readConcern:' majority 'para leitura concordada.
- Idempotidade: chaves exclusivas em 'idempotencyKey '/' pspTx', operações UPSERT ('$setOnInsert', '$ inc').
js db.wallet.updateOne(
{ playerId: "p123" },
{ $inc: { balanceCents: -5000 }, $set: { updatedAt: new Date() } },
{ upsert: true, writeConcern: { w: "majority" } }
);
Charding e seleção de chaves
Ele é um shard key. A seleção é crítica:- Alocação de carga: chave de alta radicalidade e distribuição uniforme (por exemplo, '(tenantId, playerId)').
- Evite a monotonia de 'createdAt' como a única chave → um shard quente.
- O Hased distribui as gravações.
- Ranged é melhor para as solicitações de faixa, mas vigie as caudas quentes.
- Área-charding (tag ranges) para regulação/localização (EU/LatAm/TR).
js sh.enableSharding("igaming");
db.bets.createIndex({ tenantId: 1, playerId: 1, _id: "hashed" });
sh.shardCollection("igaming.bets", { tenantId: 1, playerId: 1, _id: "hashed" });
Antipattern:
- A chave shard de baixa cardinalidade ('status') é uma distorção de chardes.
- Frequentes '$ lookup' entre coleções curtidas sem co-charding de uma chave.
- Shard key modificável (é difícil e caro alterar).
Réplicas, leituras e políticas de read-after-write
Réplica-set = HA e base de transações.
Read Preference:- 'primary' para os críticos read-after-write;
- 'primaryPreferred '/' segundary' - para analistas/não críticos.
- Read/Write concern concordar com o SLO e o orçamento latency.
Mudança Streams, CDC e integração
Mudar Streams: subscrição de inserções/updates/remoções - conveniente para:- sincronização de camadas de dinheiro (Redis),
- desencadeadores CRM/notificações,
- download para OLAP (ClickHouse/Pinot),
- telas a jato.
- Outbox-pattern: Para domínios críticos, publique eventos em uma coleção separada, que depois lê o conector e transmita para um pneu (Kafka). Isso aumenta a previsibilidade das integrações.
Observabilidade e SLO
SLO: p99 leituras de cartões ≤ 10-20 ms; inserir eventos ≤ 20-40 ms; diferença de leitensis entre chardes dentro de X%; disponibilidade ≥ 99. 9%.
Métricas: op. latência, queue depth,% de jumps para estatísticas secundárias, cachê/WT, page faults, lock-wits, pol-in de cursores/conexões abertos.
Perfilando 'system. profile ',' explain ('executionStats') ', bloqueio de colecções/índice.
Alerts: crescimento do WT cache pressure, operações lentas, crescimento do índice de solicitação não incluído, atraso secundário, chunk migrações/balanço.
Desempenho e sintonização
WiredTiger Cachê: Padrão de £50% RAM - Valide para o perfil.
Composto: snappy/zstd para coleções, zstd para revistas - balanço CPU/IO.
Inserções batch e bulkWrite para telemetria.
Project ('\field: 1 a.') para não arrastar documentos «gordos».
Limit/Skip: evite os grandes 'skip' → use a paginação por cursor/marcador ('createdAt/_ id').
Colecção Caped para logs «anéis».
Segurança e Complacência
Auth/RBAC: papéis na coleção/BD, o mínimo de privilégios necessários.
TLS em trânsito, criptografia em disco (FLE/at-rest).
Políticas PII: camuflagem/pseudônimo, coleções individuais para campos sensíveis.
Multi-Tenência: prefixos/BD/coleções individuais, filtros por 'tenantId', e você pode usar camadas RLS similares no aplicativo.
Auditoria: inclua a auditoria de operações em coleções críticas.
Bacapes, PITR e DR
Instantâneos (snapshots) de volume + opog-bacapes para o Ponto-in-Time Recovery.
Réplica set em outra região para DR.; exercícios regulares de recuperação.
Controle de crescimento oplog para picos de inserção (PSP webhooks/torneios).
Os shard clusters incluem bacapes alinhados com um servidor config.
Integração com o resto da arquitetura
CQRS: Comandos batem em SQL (dinheiro), eventos → Materialized Views em MongoDB.
Event-Streaming: Kafka/Pulsar como pneu, Mongo - sink/fonte através de conectores e de Mudar Streams.
Redis: ao lado como uma camada de ultra-baixa latência (cachês/contadores).
OLAP: descarregar em ClickHouse/Pinot para raias longas e BI.
Folha de cheque de implementação
1. Verifique os domínios do Mongo (TPS/projeção flexível/alta) que permanece no SQL.
2. Defina schema contracts: JSON Schema Validation, 'schemaVersion'.
3. Projete os índices para as solicitações reais; adicione TTL para dados «ruidosos».
4. Selecione shard key (alta cardenalidade, uniformidade); se necessário, zona-charding.
5. Configure a réplica-set, Read/Write Concern para SLO; política read-after-write.
6. Inclua observação e perfilagem, alertas para índices/WT cache/oplog.
7. Organize bacapes + PITR, DR. cluster e exercícios regulares.
8. Ligue o Mudança Streams/Outbox para sincronizar o dinheiro e os pneus.
9. Limite o tamanho dos documentos e os anexos; implemente a paginação pelo cursor.
10. Políticas individuais para PII/tenantes, criptografia, auditoria.
Antipattern
«Sem esquema» em venda: falta de validação e versões → caos.
Chaves de tempo/monótono - shard quente e p99 instável.
Joyne '$ lookup' em conjuntos enormes sem índice/paginação.
Usar transações em todo o lado - perda de desempenho.
A falta de TTL/retenção para os logs → o aumento do volume e do custo.
Armazenar invariantes em dinheiro crucial apenas em Mongo sem uma idempotação rigorosa.
Resumo
MongoDB é uma ferramenta poderosa para domínios flexíveis de iGaming, como perfis, diretórios, telemetria, projeções e personalização. A chave para o sucesso é o esquema-contrato e validação, a indexação elaborada, o shard key bem escolhido, o Read/Write Concern consciente, a Mudança Streams para as integrações e a disciplina operacional rígida (observabilidade, bacapes, DR). Combinado com o SQL Core e pneu de streaming, isso dá à plataforma interfaces rápidas e resistência sob picos de torneio.