Qual banco de dados poderia lidar com o armazenamento de bilhões / trilhões de registros?

75

Estamos pensando em desenvolver uma ferramenta para capturar e analisar dados de fluxo de rede, dos quais coletamos enormes quantidades de. A cada dia, capturamos cerca de 1,4 bilhão de registros de fluxo, com a seguinte aparência no formato json:

{
   "tcp_flags": "0",
   "src_as": "54321",
   "nexthop": "1.2.3.4",
   "unix_secs": "1352234521",
   "src_mask": "23",
   "tos": "0",
   "prot": "6",
   "input": "105",
   "doctets": "186",
   "engine_type": "0",
   "exaddr": "2.3.4.5",
   "engine_id": "2",
   "srcaddr": "9.8.7.6",
   "dst_as": "12345",
   "unix_nsecs": "752265174",
   "sysuptime": "2943529544",
   "dst_mask": "24",
   "dstport": "80",
   "last": "2943523241",
   "srcport": "52672",
   "dpkts": "4",
   "output": "111",
   "dstaddr": "6.5.4.3",
   "first": "2943517993"
}

Gostaríamos de poder fazer pesquisas rápidas (menos de 10 segundos) no conjunto de dados, provavelmente em períodos de tempo mais estreitos (intervalos de 10 a 30 m). Também queremos indexar a maioria dos pontos de dados para que possamos fazer pesquisas rapidamente em cada um deles. Também gostaríamos de ter uma visualização atualizada dos dados quando as pesquisas são executadas. Seria ótimo permanecer no mundo do código aberto, mas não nos opomos a procurar soluções proprietárias para este projeto.

A idéia é manter aproximadamente um mês de dados, o que equivaleria a 43,2 bilhões de registros. Uma estimativa aproximada de que cada registro conteria cerca de 480 bytes de dados, equivaleria a ~ 18,7 terabytes de dados em um mês, e talvez três vezes isso com índices. Eventualmente, gostaríamos de aumentar a capacidade desse sistema para armazenar trilhões de registros.

Avaliamos (basicamente) o couchbase, cassandra e mongodb na medida do possível candidato a esse projeto, no entanto, cada um propõe seus próprios desafios. Com o couchbase, a indexação é feita em intervalos e não durante a inserção dos dados, para que as visualizações não estejam atualizadas, os índices secundários do cassandra não são muito eficientes no retorno de resultados, pois normalmente exigem a varredura de todo o cluster em busca de resultados, e o mongodb parece promissor, mas parece ser muito mais difícil de escalar, pois é mestre / escravo / fragmentado. Alguns outros candidatos que planejamos avaliar são elasticsearch, mysql (não tenho certeza se isso é aplicável) e alguns bancos de dados relacionais orientados a colunas. Qualquer sugestão ou experiência do mundo real seria apreciada.

somecallmemike
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Paul White

Respostas:

57

Em uma empresa em que trabalho, estamos lidando com uma quantidade semelhante de dados (cerca de 10 TB de dados pesquisáveis ​​em tempo real). Resolvemos isso com Cassandra e eu gostaria de mencionar algumas idéias que permitirão que você faça a pesquisa O (1) em um banco de dados com várias TBs. Porém, isso não é específico para o Cassandra db, você pode usá-lo com outros db também.

Teoria

  • Compartilhe seus dados. Não há como um único servidor manter esse volume de dados de maneira confiável e realista.
  • Esteja pronto para falhas de hardware e falhas de nó inteiro, duplique os dados.
  • Comece a usar muitos servidores de back-end desde o início.
  • Use muitos servidores de commodities mais baratos, em comparação aos servidores de alto desempenho de ponta.
  • Verifique se os dados estão igualmente distribuídos entre os shards.
  • Gaste muito tempo planejando suas consultas. Derive a API das consultas e crie cuidadosamente tabelas. Esta é a tarefa mais importante e prolongada.
  • No Cassandra, você pode criar uma chave de coluna composta e obter acesso a essa chave em O (1). Gaste tempo trabalhando neles. Isso será usado para acessar registros pesquisáveis ​​em vez do índice secundário.
  • Faça uso de linhas largas. Eles são úteis para armazenar eventos com registro de data e hora.
  • Nunca realize a varredura completa ou, de fato, qualquer operação além de O (Log N) nesse volume. Se você precisar de algo mais que O (Log N), descarregue essas operações para os algoritmos Map-Reduce.

Prática

  • Não gaste tempo criando imagens do sistema operacional ou instalando servidores em máquinas físicas. Use provedores baseados em nuvem para prototipagem rápida. Trabalhei com o Amazon EC2 e posso recomendá-lo por sua simplicidade, confiabilidade e velocidade de prototipagem.
  • As máquinas Windows tendem a ser mais lentas durante o tempo de inicialização e consomem consideravelmente mais recursos no estado ocioso. Considere usar o sistema operacional baseado em Unix. Pessoalmente, achei o servidor Ubuntu um sistema operacional confiável, mas além disso, há uma comunidade muito boa no askubuntu
  • Pense em redes, idealmente, os nós devem estar próximos uns dos outros para permitir fofocas rápidas e troca de metadados.
  • Não entre em casos extremos: linhas de colunas realmente grandes ou famílias de colunas excepcionalmente longas (tabelas). O melhor desempenho é alcançado nos limites sãos - se o db suportar muitas N linhas por design, isso não significa que ele tenha um bom desempenho.
  • Nossa pesquisa leva cerca de 3-5 segundos, muito se deve aos nós intermediários entre a interface do usuário e o banco de dados. Considere como aproximar os pedidos do banco de dados.
  • Use um balanceador de carga de rede. Escolha um já estabelecido. Usamos o HAProxy, que é simples, mas rápido demais. Nunca tive problemas com isso.
  • Prefira simplicidade a soluções complexas.
  • Procure soluções gratuitas de código aberto, a menos que você tenha o backup do orçamento de tamanho de uma corporação. Depois de usar mais de vários servidores, os custos de infraestrutura podem subir muito alto.

Não trabalho para a Amazon e não tenho relações com as equipes HAProxy e Ubuntu. Esta é uma opinião pessoal e não qualquer tipo de promoção.

oleksii
fonte
5
Tenho certeza de que uma pesquisa O (1) é impossível além de casos extremamente triviais / inúteis.
Fitzsimmons
2
Não se ofenda, mas diga isso ao Google. O (1) a pesquisa é possível na escala PB sob um design cuidadoso.
Oleksii
9
@oleksii Os orçamentos de bilhões de dólares do Google não são uma comparação razoável para se desenhar.
Mark Storey-Smith
4
Eu posso conectar os 3 comentários anteriores comO(1) search <=> unbounded storage space <=> unlimited supply of cash
ypercubeᵀᴹ
3
O (1) a pesquisa de um único registro pode ser feita com uma tabela de hash linear. . No entanto, isso não fornece nenhuma eficiência na pesquisa sequencial (por intervalos). Para isso, são necessárias algumas variantes de uma estrutura BTree, que é O (log n) para um único item.
ConcernedOfTunbridgeWells
41

Se eu fosse colocar isso no SQL Server, sugeriria uma tabela como:

CREATE TABLE tcp_traffic
(
    tcp_traffic_id bigint constraint PK_tcp_traffic primary key clustered IDENTITY(1,1)
    , tcp_flags smallint    /* at most 9 bits in TCP, so use SMALLINT */
    , src_as int        /* Since there are less than 2 billion A.S.'s possible, use INT */
    , netxhop bigint    /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , unix_secs bigint  
    , src_mask int      /* an assumption */
    , tos tinyint       /* values are 0-255, see RFC 791 */
    , prot tinyint      /* values are 0-255, see RFC 790 */
    , input int         /* an assumption */
    , doctets int       /* an assumption */
    , engine_type int   /* an assumption */
    , exaddr bigint     /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , engine_id int     /* an assumption */
    , srcaddr bigint    /* use a big integer for the IP address instead of storing
                             it as dotted-decimal */
    , dst_as int        /* Since there are less than 2 billion A.S.'s possible, use INT */
    , unix_nsecs bigint /* an assumption */
    , sysuptime bigint  /* an assumption */
    , dst_mask int      /* an assumption */
    , dstport smallint  /* ports can be in the range of 0 - 32767 */
    , [last] bigint     /* an assumption */
    , srcport smallint  /* ports can be in the range of 0 - 32767 */
    , dpkts int         /* an assumption */
    , output int        /* an assumption */
    , dstaddr bigint    /* use a big integer for the IP address instead of storing
                            it as dotted-decimal */
    , [first] bigint    /* an assumption */
);

Isso resulta em um requisito de armazenamento total estimado para a tabela única, sem índices adicionais de 5,5 TB para 43,2 registros de abelha (o seu requisito especificado). Isso é calculado como 130 bytes para os próprios dados, mais 7 bytes por linha de sobrecarga, mais 96 bytes por página de sobrecarga. O SQL Server armazena dados em páginas de 8 KB, permitindo 59 linhas por página. Isso equivale a 732.203.390 páginas para um único mês de dados.

O SQL Server gosta de gravar no disco em blocos de 8 páginas (64 KB), o que equivale a 472 linhas por E / S física. Com 16.203 registros de fluxo sendo gerados a cada segundo, você precisará de uma taxa de E / S mínima de 34 IOps, garantida a cada segundo. Embora isso por si só não seja uma quantidade enorme, outras E / S no sistema (SQL Server e outras) precisam nunca infringir essa taxa necessária de IOps. Portanto, você precisaria projetar um sistema capaz de, pelo menos, mais IOps de ordem de magnitude ou 340 IOps sustentadas - eu tenderia a estimar que você precisa de 2 ordens de magnitude de IOps mais sustentáveis ​​para garantir o rendimento.

Você notará que não estou armazenando os endereços IP em sua forma decimal pontilhada. Isso economiza uma quantidade enorme de armazenamento (7 bytes por endereço) e também torna a indexação, recuperação, classificação e comparação de endereços IP muito mais eficientes. A desvantagem aqui é que você precisa converter os IPs decimais pontilhados em números inteiros de 8 bytes antes de armazená-los e voltar para IPs decimais pontilhados para exibição. O código para fazer isso é trivial; no entanto, sua taxa de linhas adicionará uma quantidade substancial de sobrecarga de processamento a cada linha de fluxo sendo processada - convém fazer esse processo de conversão em uma máquina fisicamente diferente do SQL Server.

Discutir os índices necessários é um assunto totalmente separado, pois você não listou nenhum requisito específico. O design desta tabela armazenará as linhas de fluxo na ordem física em que são recebidas pelo SQL Server, o tcp_traffic_idcampo é exclusivo para cada registro e permite classificar as linhas pela ordem em que foram gravadas (neste caso, provavelmente relacionando um a um) para a hora do evento de fluxo).

Max Vernon
fonte
4
Eu provavelmente usaria binary(4)ou binary(16), respectivamente. 4 bytes / linha adiciona muito armazenamento quando multiplicado por 1.000.000.000.000.000.
precisa
2
E os números de porta têm um intervalo de 0 a 65535, para que você possa usar, SMALLINTmas também deve haver uma rotina de conversão.
ypercubeᵀᴹ
7
@ MrTelly eu discordo. Fazer isso no SQL Server é caro apenas se você precisar de HA ou grandes itens de failover. Para um armazenamento de dados sólido e fácil de conviver, o SQL Server é ótimo para isso. Todos os sistemas ficam muito caros (e complicados) se for necessário HA.
samsmith
2
IMO, o SQL Server pode definitivamente armazenar os dados; Ainda não tenho certeza se é a solução certa para resolver a parte de análise do projeto, principalmente porque não estou familiarizado o suficiente com os outros sistemas que estão sendo considerados.
precisa
3
@ Mrrelly Existem duas despesas: a) Armazenamento em disco (de 5 a 8 tb, dependendo do espaço usado pelos índices) b) RAM (para suportar consultas, armazenamento em cache do índice). Para fazer isso monoliticamente, geralmente seria feito com uma grande matriz RAID10 ou SAN. No entanto, observe que o sharding certamente pode ser feito e pode permitir que você use a lógica no nível do aplicativo para fragmentar a carga de trabalho em vários servidores SQL. Isso pode permitir que você use servidores baratos, com 0,5-2 TB cada, e talvez até use a edição gratuita do SQL Server. (Note que sharding é um conceito genérico, muitas vezes é feito no nível do aplicativo, e se aplica a qualquer método de persistência)
samsmith
5

Eu recomendaria HBase . Você pode armazenar todos os dados brutos em uma ou mais tabelas HBase, dependendo do que você precisa consultar. O HBase pode lidar com grandes conjuntos de dados e faz o compartilhamento automático através de divisões de região.

Além disso, se você projetar bem as chaves de linha, poderá obter consultas extremamente rápidas, inclusive O (1). Observe que, se você estiver recuperando um grande conjunto de dados, isso ainda será lento, pois a recuperação de dados é uma operação O (n).

Como você deseja consultar em cada campo, eu recomendaria a criação de uma tabela exclusiva para cada um deles. Exemplo para os dados src_address, tenha uma tabela parecida com esta:

1.2.3.4_timestamp1 : { data }
1.2.3.4_timestamp2 : { data }

Portanto, se você deseja consultar todos os dados no 1.2.3.4, iniciando de 27 de março às 00:00 e 27 de março às 12:01, pode fazer uma varredura de intervalo com as linhas de início e parada especificadas.

IMHO, o design da chave de linha é a parte mais crítica do uso do HBase - se você o projetar bem, poderá fazer consultas rápidas E armazenar grandes volumes de dados.

Suman
fonte
3

Disse isto :

... não nos opomos a procurar soluções proprietárias para este projeto

Sugiro considerar o banco de dados IBM Informix + DataSeries TimeSeries . Ao contrário do que algumas pessoas dizem, o Informix está vivo e indo muito bem. A última versão foi lançada no mês passado (março / 2013, versão 12.10).

O TimeSeries é como um "plugin" (gratuito) capaz de lidar com situações como a sua.
E você pode usá-lo em produção com a versão gratuita do banco de dados Informix ( edição Innovator-C ). (claro, apenas para avaliar as partes técnicas, pois a versão gratuita possui muitos recursos limitados)

Aqui você pode verificar um PDF de referência que pode ser usado como referência. Aqui estão duas apresentações com exemplos mais técnicos: guia de manequins e outras dicas

Como não tenho experiência pessoal com o TimeSeries , não posso concordar que seja "a solução", apenas uma sugestão para avaliar.

ceinmart
fonte
2

Segundo a recomendação de examinar o Informix TimeSeries. A literatura da IBM afirma que o TimeSeries pode armazenar esse tipo de informação em 1/5 do espaço e executar 5 vezes mais rápido que as tabelas relacionais tradicionais.

Benefícios adicionais seriam a Interface da Tabela Virtual que pode fazer com que os dados do TimeSeries apareçam como tabelas relacionais tradicionais para o usuário final (simplificando o desenvolvimento de aplicativos enquanto ainda obtém os benefícios do TimeSeries), HA simples com nós HDR que agora suportam dados do TimeSeries na versão 12.1 e integração de dados do TimeSeries no Informix Warehouse Accelerator que pode ser usado para acelerar relatórios complicados de data warehouse e a capacidade de criar um protótipo de uma solução TimeSeries no Informix usando as edições gratuitas Informix Developer ou Innovator-C.

Andrew
fonte