¿Qué base de datos podría manejar el almacenamiento de miles de millones / billones de registros?

75

Estamos buscando desarrollar una herramienta para capturar y analizar datos de flujo de red, de los cuales reunimos enormes cantidades de. Cada día capturamos alrededor de ~ 1.400 millones de registros de flujo que se verían así en 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"
}

Nos gustaría poder realizar búsquedas rápidas (menos de 10 segundos) en el conjunto de datos, muy probablemente en intervalos de tiempo estrechos (intervalos de 10 a 30 minutos). También queremos indexar la mayoría de los puntos de datos para poder hacer búsquedas en cada uno de ellos rápidamente. También nos gustaría tener una vista actualizada de los datos cuando se ejecutan las búsquedas. Sería genial permanecer en el mundo del código abierto, pero no nos oponemos a buscar soluciones patentadas para este proyecto.

La idea es mantener aproximadamente un mes de datos, que serían ~ 43.2 mil millones de registros. Una estimación aproximada de que cada registro contendría aproximadamente 480 bytes de datos equivaldría a ~ 18.7 terabytes de datos en un mes, y tal vez tres veces más que con los índices. Finalmente, nos gustaría aumentar la capacidad de este sistema para almacenar billones de registros.

Hemos evaluado (muy básicamente) couchbase, cassandra y mongodb en la medida de lo posible como candidatos para este proyecto, sin embargo, cada uno propone sus propios desafíos. Con couchbase, la indexación se realiza a intervalos y no durante la inserción de los datos, por lo que las vistas no están actualizadas, los índices secundarios de cassandra no son muy eficientes para devolver resultados, ya que generalmente requieren escanear todo el clúster en busca de resultados, y mongodb parece prometedor, pero parece ser mucho más difícil de escalar ya que es maestro / esclavo / fragmentado. Algunos otros candidatos que planeamos evaluar son elasticsearch, mysql (no estoy seguro de si esto es aplicable) y algunas bases de datos relacionales orientadas a columnas. Cualquier sugerencia o experiencia del mundo real sería apreciada.

alguna llamada
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Paul White

Respuestas:

57

En una empresa para la que trabajo, estamos tratando con una cantidad similar de datos (alrededor de 10 TB de datos de búsqueda en tiempo real). Resolvemos esto con Cassandra y me gustaría mencionar un par de ideas que le permitirán hacer una búsqueda O (1) en una base de datos de múltiples TB. Sin embargo, esto no es específico de Cassandra db, también puede usarlo con otros db.

Teoría

  • Fragmenta tus datos. No hay forma de que un solo servidor retenga ese volumen de datos de manera confiable y realista.
  • Esté preparado para fallas de hardware y fallas de nodo completo, duplique los datos.
  • Comience a usar muchos servidores de fondo desde el principio.
  • Utilice muchos servidores básicos más baratos, en comparación con los de alto rendimiento de gama alta.
  • Asegúrese de que los datos se distribuyan por igual entre los fragmentos.
  • Dedique mucho tiempo a planificar sus consultas. Derive API de las consultas y luego diseñe cuidadosamente las tablas. Esta es la tarea más importante y prolongada.
  • En Cassandra, puede diseñar una clave de columna compuesta y obtener acceso a esa clave en O (1). Pasa tiempo trabajando en ellos. Esto se usará para acceder a registros de búsqueda en lugar de un índice secundario.
  • Haz uso de hileras anchas. Son útiles para almacenar eventos con marca de tiempo.
  • Nunca realice una exploración completa o, de hecho, ninguna operación más que O (Log N) en dicho volumen. Si necesita algo más que O (Log N), descargue dichas operaciones a los algoritmos Map-Reduce.

Práctica

  • No pierda el tiempo creando imágenes del sistema operativo o instalando servidores en máquinas físicas. Utilice proveedores basados ​​en la nube para la creación rápida de prototipos. Trabajé con Amazon EC2 y puedo recomendarlo por su simplicidad, confiabilidad y velocidad de creación de prototipos.
  • Las máquinas Windows tienden a ser más lentas durante el tiempo de arranque y requieren muchos más recursos en estado inactivo. Considere usar un sistema operativo basado en Unix. Personalmente, encontré que el servidor Ubuntu es un sistema operativo confiable, pero además hay una comunidad bastante buena en askubuntu
  • Piense en las redes, los nodos idealmente deben estar cerca uno del otro para permitir el intercambio rápido de meta-datos y cotilleos.
  • No entre en casos extremos: filas de columnas realmente anchas o familias de columnas excepcionalmente largas (tablas). El mejor rendimiento se logra en los límites sanos: si db admite esa cantidad de N filas por diseño, no significa que funcione bien.
  • Nuestra búsqueda tarda unos 3-5 segundos, mucho se debe a los nodos intermedios entre la interfaz de usuario y la base de datos. Considere cómo acercar las solicitudes a la base de datos.
  • Use un equilibrador de carga de red. Elige uno establecido. Usamos HAProxy, que es simple, pero muy rápido. Nunca tuve problemas con eso.
  • Prefiere simplicidad a soluciones complejas.
  • Busque soluciones gratuitas de código abierto, a menos que esté respaldado por el presupuesto del tamaño de una empresa. Una vez que vaya a más de varios servidores, los costos de la infraestructura podrían subir mucho.

No trabajo para Amazon y no tengo relaciones con los equipos HAProxy y Ubuntu. Esta es una opinión personal en lugar de cualquier tipo de promoción.

oleksii
fuente
55
Estoy bastante seguro de que una búsqueda O (1) es imposible, aparte de casos extremadamente triviales / inútiles.
Fitzsimmons
2
No te ofendas, pero díselo a Google. O (1) búsqueda es posible en la escala PB bajo un diseño cuidadoso.
oleksii
9
@oleksii Los presupuestos de Google de miles de millones de dólares no son una comparación razonable para dibujar.
Mark Storey-Smith
44
Puedo conectar los 3 comentarios anteriores conO(1) search <=> unbounded storage space <=> unlimited supply of cash
ypercubeᵀᴹ
3
O (1) la búsqueda de un solo registro se puede hacer con una tabla hash lineal. . Sin embargo, esto no le brinda ninguna eficiencia en la búsqueda secuencial (para rangos). Para esto, necesita alguna variante de una estructura BTree, que es O (log n) para un solo elemento.
ConcernedOfTunbridgeWells
41

Si fuera a poner esto en SQL Server, sugeriría una tabla similar a:

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 */
);

Esto da como resultado un requisito de almacenamiento total estimado para la tabla individual, sin índices adicionales de 5.5 TB para 43.2 registros de beeellion (su requisito especificado). Esto se calcula como 130 bytes para los datos en sí, más 7 bytes por fila de sobrecarga, más 96 bytes por página de sobrecarga. SQL Server almacena datos en páginas de 8 KB, lo que permite 59 filas por página. Esto equivale a 732,203,390 páginas para un solo mes de datos.

A SQL Server le gusta escribir en el disco en fragmentos de 8 páginas (64 KB), lo que equivale a 472 filas por E / S física. Con 16,203 registros de flujo generados por segundo, necesitará una tasa de E / S mínima de 34 IOps, garantizada cada segundo. Aunque esto por sí solo no es una gran cantidad, otras E / S en el sistema (SQL Server y otros) no deben infringir nunca esta tasa necesaria de IOps. Por lo tanto, necesitaría diseñar un sistema capaz de al menos un orden de magnitud más IOps, o 340 IOps sostenidas. Tendería a estimar que necesita 2 órdenes de magnitud de IOps más sostenibles para garantizar el rendimiento.

Notará que no estoy almacenando las direcciones IP en su forma decimal punteada. Esto ahorra una gran cantidad de almacenamiento (7 bytes por dirección), y también hace que la indexación, recuperación, clasificación y comparación de direcciones IP sean mucho, mucho más eficientes. La desventaja aquí es que necesita convertir las IP decimales punteadas en enteros de 8 bytes antes de almacenarlas, y volver a las IP decimales punteadas para su visualización. El código para hacerlo es trivial, sin embargo, su velocidad de fila esto agregará una cantidad sustancial de sobrecarga de procesamiento a cada fila de flujo que se procesa; es posible que desee realizar este proceso de conversión en una máquina físicamente diferente de SQL Server.

Discutir los índices que necesita es una cuestión totalmente diferente, ya que no ha enumerado ningún requisito específico. El diseño de esta tabla almacenará las filas de flujo en el orden físico en que las recibe SQL Server, el tcp_traffic_idcampo es único para cada registro y permite ordenar las filas por el orden en que se registraron (en este caso, lo más probable es que se relacionen uno a uno a la hora del evento de flujo).

Max Vernon
fuente
44
Probablemente usaría binary(4)o binary(16), respectivamente. 4 bytes / fila agrega mucho almacenamiento cuando se multiplica por 1,000,000,000,000.
Jon Seigel
2
Y los números de puerto tienen un rango de 0-65535, por lo que puede usarlo, SMALLINTpero también tiene que haber una rutina de conversión.
ypercubeᵀᴹ
77
@ MrTelly no estoy de acuerdo. Hacerlo en SQL Server es costoso solo si necesita HA o grandes cosas de failover. Para un almacén de datos sólido, con el que es realmente fácil vivir, SQL Server es ideal para esto. Todos los sistemas se vuelven muy caros (y complicados) si se necesita HA.
samsmith
2
OMI, SQL Server definitivamente puede almacenar los datos; Todavía no estoy seguro de si es la solución correcta para resolver la parte analítica del proyecto, principalmente porque no estoy lo suficientemente familiarizado con los otros sistemas que se están considerando.
Jon Seigel
3
@MrTelly Hay dos gastos: a) Almacenamiento en disco (para 5-8 tb, dependiendo del espacio utilizado por los índices) b) RAM (para admitir consultas, almacenamiento en caché de índices). Hacer esto monolíticamente generalmente se haría con una gran matriz RAID10 o SAN. Sin embargo, tenga en cuenta que el fragmentación ciertamente se puede hacer, y podría permitirle usar la lógica de nivel de aplicación para fragmentar la carga de trabajo en múltiples servidores SQL. Esto podría permitirle usar servidores baratos, con 0.5-2tb cada uno, y quizás incluso usar la edición gratuita de SQL Server. (Tenga en cuenta que el fragmentación es un concepto genérico, a menudo se realiza a nivel de aplicación y se aplica a cualquier método de persistencia)
samsmith
5

Yo recomendaría HBase . Puede almacenar todos los datos sin procesar en una o más tablas de HBase, según lo que necesite consultar. HBase puede manejar grandes conjuntos de datos y se auto-fragmenta a través de divisiones de región.

Además, si diseña bien las teclas de fila, puede obtener consultas extremadamente rápidas, incluso O (1). Tenga en cuenta que si está recuperando un conjunto de datos grande, eso seguirá siendo lento ya que recuperar datos es una operación O (n).

Como desea consultar en cada campo, le recomendaría crear una tabla única para cada uno de ellos. Ejemplo para los datos de src_address, tenga una tabla que se vea así:

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

Entonces, si desea consultar todos los datos en 1.2.3.4 a partir del 27 de marzo a las 12:00 a.m. hasta el 27 de marzo a las 12:01 a.m., puede hacer un escaneo de rango con las filas de inicio y detención especificadas.

En mi humilde opinión, el diseño de la clave de fila es la parte más crítica del uso de HBase: si lo diseña bien, podrá realizar consultas rápidas Y almacenar grandes volúmenes de datos.

Suman
fuente
3

Dijo esto :

... no nos oponemos a buscar soluciones patentadas para este proyecto

Sugiero considerar IBM Informix base de datos + TimeSeries DataBlade. Frente a lo que dicen algunas personas, Informix está vivo y va muy bien. La última versión se lanzó el mes pasado (marzo / 2013, versión 12.10).

TimeSeries es como un "complemento" (sin costo) capaz de manejar situaciones como la suya.
Y puede usarlo en producción con la versión gratuita de la base de datos Informix ( edición Innovator-C ). (por supuesto, solo para evaluar las partes técnicas ya que la versión gratuita tiene muchos recursos limitados)

Aquí puede consultar un PDF de referencia que se puede utilizar como referencia. Aquí dos presentaciones con más ejemplos técnicos: guía de maniquíes y otros consejos.

No tengo experiencia personal con TimeSeries , por lo que no puedo aceptar que sea "la solución", solo una sugerencia para evaluar.

ceinmart
fuente
2

Secundo la recomendación de mirar Informix TimeSeries. La literatura de IBM afirma que TimeSeries puede almacenar este tipo de información en 1/5 del espacio y funcionar 5 veces más rápido que las tablas relacionales tradicionales.

Beneficios adicionales serían la Interfaz de tabla virtual que puede hacer que los datos de TimeSeries aparezcan como tablas relacionales tradicionales para el usuario final (simplificando el desarrollo de la aplicación y al mismo tiempo obteniendo los beneficios de TimeSeries), HA simple con nodos HDR que ahora admiten datos de TimeSeries en la versión 12.1 y el integración de datos de TimeSeries en Informix Warehouse Accelerator que puede usarse para acelerar informes complicados de almacenamiento de datos y la capacidad de crear prototipos de una solución TimeSeries en Informix utilizando las ediciones gratuitas Informix Developer o Innovator-C.

Andrés
fuente