Esquema de datos NoSQL para el análisis de logs de acceso a Internet

Publicado
Comentarios:  Ninguno

Análisis de logs con NoSQL

El análisis de logs (a posteriori o en tiempo real) es el tipo de problema para el que las soluciones NoSQL están particularmente indicadas. Tenemos una gran (sino enoooorme) cantidad de datos que aumenta indefinidamente y no necesitamos establecer relaciones en el diseño del esquema de base de datos.

Hoy en día en mi empresilla familar este trabajo se está haciendo con MySQL. En este artículo explicaré el diseño del esquema elegido para una posible solución implementada con MongoDB

Descripción de la base de datos MySQL

En nuestra instalación actual de MySQL las tablas están particionadas horizontalmente por mes, debido a su gran tamaño.

Simplificando, están definidas las siguientes tablas:

Logs de acceso

  • “Log de acceso a Internet” para conexiones no FTP, con campos para
    • IP del usuario
    • Identificador del usario
    • Fecha y hora
    • Método usado (GET, POST, etc.)
    • Protocolo
    • Dominio de destino
    • URI de destino
    • Código de retorno
    • Tamaño en bytes
  • “Log de transferencias FTP, con campos para
    • IP del usuario
    • Identificador del usario
    • Fecha y hora
    • Método FTP usado
    • Dominio y puerto de destino
    • URI de destino
    • Tamaño en bytes

Informes por mes

Los totales mensuales por dominio y usuario para son calculados y almacenados en tablas separadas

  • “Totales por dominio”, un registro por cada uno, con campos para
    • Nombre del dominio
    • Número total de accesos por dominio
    • Volumen en bytes descargado
  • “Totales por usuario”, con campos para
    • Nombre del usuario
    • Número total de accesos por usuario
    • Volumen en bytes descargado

Tamaño de los datos

En producción almacenamos cada mes entre 250 y 300 Gigabytes, lo que hace más de 3,5 Terabytes al año (por lo general los datos se mantendrá por un año)

Cada mes, y teniendo en cuenta las tablas descritas, el número de registros de acceso guardados son aproximadamente:

  • Para el log de accesos no FTP: más de 1.500 millones de registros
  • Para el log de accesos FTP: entre 300.000 y 750.000

Para un número aproximado mensual de 80.000 usuarios y 2,5 millones de dominios

Definición de un esquema para MongoDB NoSQL

En resumen, después de buscar en la base de datos tenemos los siguientes elementos:

  • Los usuarios
  • Los dominios de Internet
  • Los de acceso para las solicitudes de FTP
  • Los de acceso para los que no las peticiones FTP

Vamos a definir una colección para cada uno:

  • Cada registro en MySQL de los logs de acceso se corresponderá a un documento en NoSQL en una de las dos colecciones de registros de acceso
  • Los informes con los totales para cada usuario y dominio los calcularemos en tiempo real utilizando funciones de MongoDB.

En MongoDB no es necesario definir los campos y el tipo de cada campo. Después de la creación de una colección, la estructura es creada por la aplicación “just in time”.

Por tanto, la estructura de cada colección será (mostrada en pseudocódigo) …

Logs de accesos no FTP a Internet

{
    "clientip": string,
    "user":  string,
    "datetime":  Date,
    "method":  string,
    "protocol":  string,
    "domain":  string,
    "uri":  string,
    "return_code":  integer,
    "size":  integer
}

Logs de accesos FTP a Internet

{
    "clientip": string,
    "user":  string,
    "datetime":  Date,
    "method":  string,
    "domain":  string,
    "uri":  string,
    "size":  integer
}

Totales calculados por usuario

Para los informes mensuales crearemos una colección para los usuarios y otra para los dominios, con totales por mes y por día.

Para cada año y mes tendremos una colección.

En cada colección habrá un sólo documento por usuario. Además del identificador del usuario, se registrará el total de visitas y el volumen en bytes total descargado. Para cada día se crearán sobre la marcha subdocumentos (dentro del documento correspondiente al usuario) en el que se indicará los totales de ese día.

Estos totales serán actualizados en tiempo real, a medida que sea procesada cada entrada de los logs. Es decir, cada vez que se reciba la información de a una visita se creará un nuevo registro en el log (FTP o no FTP), se sumará 1 al número de visitas para el usuario y se actualizará el volumen total sumando en el día y mes correspondiente.

{
    "_id": "userid",
    "nb":  integer,
    "volume":  integer,
    "daily": {
        "0": {
            "nb":  integer,
            "volume":  integer
        },
        "1": {
            "nb":  integer,
            "volume":  integer
        },
        "2": {
            "nb":  integer,
            "volume":  integer
        },
        "3": {
            "nb":  integer,
            "volume":  integer
        },
        ....
        "30": {
            "nb":  integer,
            "volume":  integer
        },
    },
}

Totales calculados por dominio

La idea es la misma que en el caso anterior …

{
    "_id": "domain string"
    "nb":  integer,
    "volume":  integer
    "daily": {
        "0": {
            "nb":  integer,
            "volume":  integer
        },
        ....
    },
}

Artículos y presentaciones interesantes

Para entender cómo definir el diseño de la base en un servidor NoSQL para el problema que estamos planteando las siguientes presentaciones han sido de una gran utilidad:

En la página de 10Gen, la compañía creadora del producto, podemos encontrar más presentaciones sobre análisis de datos con MongoDB.

Desde un punto de vista más amplio, considerando una arquitectura de la que MongoDB formaría parte, lo dos siguientes enlaces también son interesantes:

To be continued …

Queda para artículos posteriores definir:

  • cómo he generado cantidades enormes de datos aleatorios (los datos reales son muy sensibles como para jugar con ellos)
  • las pruebas de rendimiento comparativas entre MySQL y MongoDB y las conclusiones alcanzadas.


Etiquetas:

Comentarios

Actualmente no hay comentarios a este artículo.

Añadir comentarios ...

Escribe debajo tu comentario. Los campos marcados con * son obligatorios. Tienes que previsualizar tu comentario antes de enviarlo definitivamente.