Bajo acoplamiento procesando grandes cantidades de datos

8

Por lo general, logro un bajo acoplamiento creando clases que intercambian listas, conjuntos y mapas entre ellos. Ahora estoy desarrollando una aplicación por lotes Java y no puedo poner todos los datos dentro de una estructura de datos porque no hay suficiente memoria. Tengo que leer y procesar un fragmento de datos y luego pasar al siguiente. Entonces, tener un acoplamiento bajo es mucho más difícil porque tengo que verificar en algún lugar si todavía hay datos para leer, etc.

Lo que estoy usando ahora es:

Fuente -> Proceso -> Persistir

Las clases que procesan tienen que preguntar a las clases de origen si hay más filas para leer.

¿Cuáles son las mejores prácticas y / o patrones útiles en tales situaciones?

Espero poder explicarme, si no me lo cuentas.

Виталий Олегович
fuente
3
Una de las formas de lograr un bajo acoplamiento es establecer un buen protocolo de comunicación entre las clases de origen y las clases de proceso
treecoder
3
Creo que es posible que desee ver el uso de una cola de mensajes, algún tipo de bus de datos, para que sus clases pongan las cosas en colas y las saquen de las colas en lugar de interactuar directamente.
Murph
@Murph, ¿hay una manera simple o una buena biblioteca de Java para usar una cola de mensajes?
Виталий Олегович
@vitalik: soy un desarrollador de .NET y sigo sintiéndome a gusto con las colas de mensajes en general, por lo que no estoy en condiciones de proporcionar una respuesta segura (por lo tanto, mi respuesta es comentar)
Murph
1
@Murph ok, gracias de todos modos! ¡Creo que también comenzaré a estudiar colas!
Виталий Олегович

Respuestas:

7

De los comentarios veo que estás usando Java. Eche un vistazo a varias implementaciones de cola . Particularmente, BlockingQueue es útil para escenarios productor-consumidor . Podría tener dos colas: una entre Fuente (productor de datos) y Proceso (consumidor de datos), y otra entre Proceso (productor de resultados) y Persistir (consumidor de resultados).

Con colas de bloqueo de capacidad limitada, es bastante fácil implementar sistemas eficientes (la parte del cuello de botella, sea lo que sea, se mantiene alimentada con datos el 100% del tiempo), y aún usa solo una cantidad limitada de memoria, sin importar cuántos datos haya.

Joonas Pulakka
fuente
Tu solución es muy buena. Pero, ¿qué sucede si uso una cola de capacidad limitada, y la cola está llena y trato de agregarle algo?
Виталий Олегович
@vitalik, entonces debe implementar una estrategia, como almacenar temporalmente los datos en una base de datos en memoria o en el disco de otra solución.
Martijn Verburg
@MartijnVerburg sí, pero supongo que sería más fácil si existiera la posibilidad de dormir al productor hasta que haya más espacio disponible en la cola.
Виталий Олегович
1
@vitalik, por supuesto, existe esa posibilidad (para dormir un productor) solo tienes que hacerlo. Algunas colas se pueden configurar para que se bloqueen, de modo que si un productor intenta insertarse en una cola completa, simplemente bloquea y efectivamente duerme / gira (cuidado con cuál) en la cola para tener espacio.
sdg
1
@vitalik: Consulte, por ejemplo, BlockingQueue.put docs: inserta el elemento especificado en esta cola, esperando si es necesario que haya espacio disponible. Simple y conveniente! :)
Joonas Pulakka
2

Una cola de bloqueo (de Joonas Pulakka) es la respuesta pesada. Una respuesta más simple podría funcionar. Si tiene todos los datos almacenados en la fuente, simplemente puede pasar una referencia al procesador, y puede obtener los datos de la fuente. Por supuesto, esto es probablemente lo que estabas haciendo en el pasado. Es posible que no tenga todos los datos en la memoria en la fuente y que no obtenga el bajo acoplamiento que desea.

El siguiente paso sería utilizar una interfaz Enumerator o Iterator. (Los iteradores son más comunes en Java, aunque la mayoría de las veces ese removemétodo es solo una molestia). El procesador obtendría el iterador de la fuente y luego llamaría a los métodos hasta que esté listo. Si la fuente extrae datos de terrabytes de alguna parte, cada llamada puede demorar un poco. Pero si va a dormir el procesador hasta que haya algo en la cola de todos modos, esto lo hará automáticamente. Y si la fuente se adelanta al productor, la fuente esperará automáticamente a que el productor llame hasNexty next.

Si, por otro lado, desea que la fuente tome datos de su fuente lo más rápido posible y los acumule hasta que el procesador se ponga al día, sin esperar a que el procesador procese, entonces la cola, y múltiples hilos, comienza a parecer una buena idea, aunque más complicada. Ahora, la fuente se acumulan los datos cuando se puede correr más rápido (el límite es de suponer algo así como disco I / O), y el procesador puede reducir el tamaño de la pila cuando se puede correr más rápido, (su límite es la rapidez con la persistencia módulo puede persistir los datos).

RalphChapin
fuente