2009-04-12 9 views
8

La empresa para la que trabajo crea aplicaciones para la plataforma Blackberry.¿La mejor manera de diseñar un sistema de éxitos/análisis escalable?

Hemos estado trabajando en un "sistema analítico" patentado que nos permite incorporar código dentro de nuestras aplicaciones y hacer que las aplicaciones reporten algunas estadísticas a nuestros servidores centrales cada vez que se ejecutan. Actualmente, el sistema funciona bien; sin embargo, solo está en beta con 100-200 visitas por hora. Los "hits" se envían a los servidores sin problemas. Hemos creado una API muy sólida para manejar la aceptación y el almacenamiento de los hits (en una base de datos MySQL). Hemos probado la carga y deberíamos poder acomodar cientos de miles de visitas por hora sin ningún problema. Eso no es realmente un problema.

El problema es mostrar las estadísticas. Hemos construido un panel de visualización similar al de Mint (haveamint.com), que muestra los resultados de cada hora, los últimos días, meses, semanas, años ... etc. La primera versión ejecutó consultas directas extrayendo datos de la tabla de éxitos e interpretándolos sobre la marcha. Eso no funcionó por mucho tiempo. Nuestra solución actual es que los hits están "en cola" para el procesamiento y tenemos un cron que viene cada 5 minutos tomando los hits y clasificándolos en "cachés" por cada hora, día, semana, mes, año ... etc. Esto funciona increíble y es increíblemente escalable; sin embargo, solo funciona para 1 zona horaria. Como toda la compañía tiene acceso a esto, estamos lidiando con unos pocos cientos de usuarios en varias zonas horarias. Lo que defino como "Hoy" en San José es MUCHO diferente de lo que mi colega en Londres define como Hoy. Dado que la solución actual solo se almacena en caché en 1 zona horaria, es una pesadilla para cualquiera que esté verificando los datos fuera de nuestra zona horaria.

Nuestro plan actual para solucionar esto es crear cachés para cada zona horaria (40 en total); sin embargo, eso significaría que estamos multiplicando la cantidad de datos por 40 ... eso es terrible para mí y dado que los cachés pueden ser muy grandes, multiplicarlos suena como una mala idea; Además, cuando vayamos a procesar la cola, va a llevar mucho más tiempo de CPU colocarlas en 40 cachés diferentes.

¿Alguien más tiene una mejor idea de cómo resolver este problema?

(En este momento durante mucho question..it tal no es exactamente fácil de explicar. Gracias a todos!)

+0

Tan específico como su pregunta es, en realidad estoy diseñando algo muy similar e iba a venir aquí para la entrada. +1 –

+0

Sería muy interesante ver tu API de manejo/almacenamiento de hits :) – Jacco

Respuesta

4

La solución que propones tiene demasiada redundancia. Le sugiero que almacene los datos en intervalos de al menos 30 minutos en lugar de cada hora y la zona horaria se normalice en UTC.

Con intervalos de 30 minutos, si un usuario solicita datos por hora para 1 - 2PM desde -4.5 UTC, puede buscar datos de su sistema desde las 5:30 a 6:30 PM y mostrarlos. Si almacena datos en incrementos de una hora, no puede atender solicitudes a usuarios en husos horarios con N + 0.5 horas de diferencia.

Para números diarios, necesitaría agregar 48 ranuras de media hora. Las ranuras para elegir vendrían determinadas por la zona horaria del usuario.

Se pone interesante cuando llega a los datos anuales porque termina teniendo que agregar 17.520 cubos de media hora. Para facilitar ese cálculo, le sugiero que obtenga los datos anuales preagregados por hora UTC y los restar los datos agregados para el primero durante 4.5 horas del año y agregue datos agregados para las primeras 4.5 horas del año siguiente. Esto esencialmente cambiará todo el año en 4.5 horas y el trabajo no es mucho. Trabajando desde aquí, puede ajustar más el sistema.

EDITAR: Resulta que Katmandú es +5.45 GMT por lo que necesitaría almacenar los datos en intervalos de 15 minutos en lugar de intervalos de 30 minutos.

EDIT 2: Otra mejora fácil es la agregación anual, por lo que no tiene que agregar 17.520 buckets cada vez y sin requerir un agregado por país. Agregue los datos anuales del 2 al 30 de enero. Dado que la diferencia máxima de huso horario entre dos países es de 23 horas, esto significa que puede tomar los datos anuales (del 2 al 30 de diciembre) y agregar algunos segmentos antes y después según sea apropiado. Por ejemplo, para una zona horaria de -5 UTC, agregará todos los depósitos el 1 de enero después de 0500, todos los segmentos el 31 de diciembre y el 1 de enero del año siguiente hasta las 0500 horas.

+1

+1 para la discusión sobre el tamaño del cubo – lpfavreau

+1

Esta parece ser la mejor opción. Los intervalos de 15 minutos pueden no valer la pena teniendo en cuenta que solo una cantidad muy pequeña de personas ocupará esas zonas horarias. –

2

Al diseñar software que toca múltiples zonas horarias, yo diría que a Guarde siempre la fecha/veces en UTC con otro campo para la zona horaria original y tiene una función que toma el tiempo y la convierte ay desde UTC/zona horaria. Se ahorrará muchos problemas para manejar los diferentes casos de cambio de día, ahorro de luz diurna, personas que miran estadísticas de un país del otro lado de la tierra y así sucesivamente ...

En su caso, tener las cachés en UTC y simplemente ajustar las solicitudes para convertir en UTC debería ayudar. No almacene una estadística como "hoy", guárdela durante horas 00: 00: 00UTC a 23: 59: 59UTC y cuando alguien le pregunte por las estadísticas de hoy en Nueva York, haga la conversión.

+0

No veo ningún motivo para la votación aquí. En realidad, no se trata de cómo se obtendrían datos diarios de Nueva York porque no se puede cambiar el día 5 horas. Necesita los datos de las 5 horas anteriores y debe restar las últimas 5 horas como sugerí en mi solución. – aleemb

+0

Nunca hablé sobre el tamaño del cucharón en esta solución. Solo digo que haga los cubos en UTC de 00:00 a 23:59 en lugar de la hora local. Como no hay suficientes detalles sobre qué estadísticas se proponen en la interfaz de usuario, no es posible proponer un tamaño de cubeta definitivo. – lpfavreau

+0

@aleemb: No hay ninguna razón para la votación negativa ya que usted propone exactamente lo mismo, pero amplió la discusión sobre el tamaño de los depósitos, lo cual es genial. – lpfavreau

0

Por lo que puedo ver, usted está buscando la parte de almacenamiento de un sistema de almacenamiento de datos aquí (sus informes serían el front-end).

En realidad, la forma en que los sistemas comerciales lo están haciendo es la memoria caché que describió: Preagrega las tablas y crea cachés de ellas. La única manera de acelerar sus consultas es hacer que el sistema de base de datos haga menos por ellos. Esto significa menos datos, lo que a su vez significa menos tiempo dedicado a iterar los datos o menos datos en los índices.

Dicho esto, yo propondría la "solución de 40 caché" (¿hay realmente más de 24 zonas horarias). Debería poder paralelizar trivialmente la cola de clasificación creando copias de los datos.

Otra forma de hacer esto sería almacenar en caché a la hora de granularidad y luego agregar las horas en días (o 30 minutos si sus zonas horarias lo requieren). Esto significa que almacena en caché en una granularidad más fina que su caché diaria pero en una granularidad más gruesa que los datos originales.

Cuestiones relacionadas