2009-10-15 12 views
8

Necesito almacenar registros en un almacenamiento persistente y recuperarlos bajo demanda. El requisito es el siguiente:Java Fast Data Storage & Retrieval

  1. extremadamente rápida recuperación e inserción
  2. Cada registro tendrán una clave única. Esta clave se utiliza para recuperar el registro
  3. Los datos almacenados deben ser decir persistente deben estar disponibles a JVM reiniciar
  4. Un proceso separado se movería registros obsoletos a RDBMS una vez al día

¿Qué es lo que ustedes ¿pensar? No puedo usar la base de datos estándar debido a problemas de latencia. Las bases de datos de memoria como HSQLDB/H2 tienen limitaciones de rendimiento. Además, los registros son simples objetos de cadena y no califican para SQL. Estoy pensando en algún tipo de solución basada en archivos planos. ¿Algunas ideas? Cualquier proyecto de código abierto? Estoy seguro de que debe haber alguien que haya resuelto este problema antes.

+1

¿Qué quieres decir con "Extremadamente rápido"? –

+0

Latencia de sub milisegundos para almacenar y recuperar – AAK

+2

¿cuál es su relación de escrituras a lecturas? al leer, ¿cuál es el patrón de acceso (aleatorio, agrupado, ...)? ¿Cuál es la naturaleza de la clave única para cada registro (no importa, uuid, timestamp)? – Ron

Respuesta

2

MySQL con fragmentos puede ser una buena idea. Sin embargo, depende de cuál es el volumen de datos, las transacciones por segundo y la latencia que necesita.

En las bases de datos de memoria también son una buena idea. De hecho, MySQL proporciona tablas basadas en memoria también.

+0

sí ... en las bases de datos de memoria son buenas ... pero mi experiencia previa con HSQLDB no es tan buena ... de hecho, habíamos determinado que HQSQL db estaba tomando un tiempo considerable en nuestro procesamiento ... No estoy seguro acerca de MSQL aunque – AAK

1

¿De verdad ha demostrado que usar una base de datos SQL fuera de proceso como MySQL o SQL Server es demasiado lenta, o es esto una suposición?

Puede utilizar un enfoque de base de datos SQL junto con una memoria caché en memoria para garantizar que las recuperaciones no lleguen a la base de datos. A pesar de que los registros son de texto plano, recomendaría usar SQL sobre una solución de archivo sin formato (por ejemplo, usar una columna de texto en su esquema de tabla) ya que el RDBMS realizará optimizaciones que un sistema de archivos no puede (p. Ej. .

Sin embargo, sin más información sobre sus patrones de acceso, rendimiento esperado, etc. No puedo proporcionar mucho más en el camino de las sugerencias.

+0

Sí . Nuestro sistema heredado usa RDBMS y toma unos pocos milisegundos para la recuperación de datos. Esta es una aplicación de alta frecuencia, la velocidad requerida en menos de milisegundos para el procesamiento de mensajes completos donde el almacenamiento y la recuperación son solo una parte del procesamiento de mensajes – AAK

+0

Más importante aún, ¿cuáles son sus patrones de acceso? ¿Los datos son secuenciales (por ejemplo, series de tiempo)? ¿Los datos se escriben una vez y se leen muchas veces, o se pueden actualizar potencialmente? Existen soluciones a medida para esto (por ejemplo, KDB) pero depende en gran medida de su caso de uso. – Adamski

-1

¿Te quedarán todos los registros y claves que necesites en la memoria a la vez? Si es así, puedes usar un HashMap < String, String >, ya que es Serializable.

+0

-1 de mí. Tendrá que serializar manualmente todo el HashMap en cada inserción, lo que obviamente es muy lento. –

+0

sí ... ¿pero qué hay de la persistencia de los datos en tiempo real? Necesito persistir los datos tal como aparecen, de modo que si la JVM se bloquea, no pierdo los datos ... – AAK

+0

@AAK: puede serializar y almacenar cada cambio. Entonces no tiene un almacenamiento de persistencia de uso inmediato, pero tiene un registro desde el que puede reconstruir el almacenamiento en caso de error. –

1

¿Cuánto le importa si pierde un registro o dos? ¿De dónde están viniendo? ¿Tienes una relación transaccional con la fuente?

Si tiene requisitos de confiabilidad serios, entonces creo que es posible que deba estar preparado para pagar algunos gastos generales de DB.

Quizás podría separar el problema de persistencia del problema en memoria. Use un enfoque de subcachorro. ¿Un suscriptor se ocupa de la memoria, y el otro persiste en que los datos están listos para el inicio posterior?

Los productos de cache distribuidos como WebSphere eXtreme Scale (sin dependencia Java EE) pueden ser relevantes si puede comprar en lugar de compilar.

+0

Los requisitos de confiabilidad son bastante altos. También estaba inclinado hacia alguna solución de almacenamiento en caché. EHCache? – AAK

1

¿Qué tan malo sería si pierde un par de entradas en caso de un choque?

Si no es tan malo el siguiente enfoque podría funcionar para usted:

Crear archivos planos para cada entrada, el nombre del archivo es igual a ID. Posible archivo para una cantidad no tan grande de entradas consecutivas.

Asegúrese de que su controlador tenga un buen caché y/o utilice uno de los cachés existentes implementados en Java.

Habla con un experto en el sistema de archivos cómo hacer esto muy rápido

Es simple y puede ser que sea rápido. Por supuesto que pierde transacciones incluyendo los principios ACID.

+0

Los requisitos de confiabilidad son bastante altos. No podemos darnos el lujo de perder ningún dato tras un accidente ... – AAK

4

Si todos los datos se ajustan a la memoria, MySQL puede ejecutarse en la memoria en lugar de en el disco (MySQL Cluster, Hybrid Storage). A continuación, puede gestionar su almacenamiento en el disco por usted.

1

Si está buscando una tienda de valores-clave simple y no necesita consultas complejas de sql, puede valer la pena visitar Berkeley DB.

Otra alternativa es Tokyo Cabinet, una implementación moderna de DBM.

1

Sub milisegundo r/w significa que no puede depender del disco, y debe tener cuidado con la latencia de la red. Solo olvídate de las soluciones estándar basadas en SQL, memoria principal o no. En un ms, no puede obtener más de 100 KByte en una red GBit. Pregúntele a un ingeniero de telecomunicaciones, están acostumbrados a resolver este tipo de problemas.

7

Existen muchas herramientas y métodos diversos, pero creo que ninguno de ellos puede brillar en todos los requisitos.

Para baja latencia, sólo se puede confiar en el acceso de datos en memoria - discos son físicamente demasiado lento (y los SSD también). Si los datos no caben en la memoria de una sola máquina, tenemos que distribuir nuestros datos a más nodos sumando suficiente memoria.

Para persistencia, tenemos que escribir nuestros datos en el disco después de todo. Suponiendo una organización óptima , esto se puede hacer como actividad de fondo, sin afectar la latencia. Sin embargo, para fiabilidad (failover, HA o lo que sea), las operaciones del disco no pueden ser totalmente independientes de los métodos de acceso: tenemos que esperar a que los discos modifiquen los datos para hacer que nuestra operación no desaparezca. Concurrencia también agrega cierta complejidad y latencia.

El modelo de datos no es restrictivo aquí: la mayoría de los métodos admiten el acceso basado en una clave única.

Tenemos que decidir,

  • si los datos se ajusta en la memoria de una máquina, o tenemos que encontrar soluciones distribuidas,
  • si la concurrencia es un problema, o no hay operaciones en paralelo,
  • si la fiabilidad es estricta, no podemos perder modificaciones, o podemos vivir con el hecho de que un bloqueo no planificado daría lugar a la pérdida de datos.

Las soluciones pueden ser

  • auto implementado estructuras de datos usando la biblioteca estándar de Java, archivos, etc., no pueden ser la mejor solución, porque la fiabilidad y baja latencia requieren implementaciones inteligentes y un montón de pruebas,
  • RDBMS tradicionales s tienen un modelo flexible de datos, operaciones duraderas, atómicas y aisladas, almacenamiento en caché, etc. - en realidad saben demasiado y son en su mayoría difíciles de distribuir. Es por eso que son demasiado lentas, si no puede desactivar las características no deseadas, que generalmente es el caso.
  • NoSQL y tiendas de valores-clave son buenas alternativas. Estos términos son bastante vagos y cubren muchas herramientas. Los ejemplos son
    • BerkeleyDB o Kyoto Cabinet como almacenes de valores-clave persistentes de una máquina (usando B-trees): se pueden usar si el conjunto de datos es lo suficientemente pequeño para caber en la memoria de una máquina.
    • Proyecto Voldemort como una tienda de valores-clave distribuida: utiliza BerkeleyDB java edition inside, simple y distribuido,
    • ScalienDB como almacén de clave-valor distribuido: confiable, pero no demasiado lento para las escrituras.
    • MemcacheDB, Redis otras bases de datos de almacenamiento en caché con persistencia,
    • sistemas populares NoSQL como Cassandra, CouchDB, HBase, etc.: se utiliza principalmente para big data.

Una lista de herramientas NoSQL se puede encontrar por ejemplo. here.

Voldemort's performance tests reportan tiempos de respuesta de menos de milisegundos, y estos se pueden lograr bastante fácilmente, sin embargo, también debemos tener cuidado con el hardware (como las propiedades de red mencionadas anteriormente).

3

Yo usaría un BlockingQueue para eso. Simple, y construido en Java.
Hago algo similar usando datos en tiempo real de Chicago Merchantile Exchange.
Los datos se envían a un lugar para uso en tiempo real ... y a otro lugar (a través de TCP), usando un BlockingQueue (Productor/Consumidor) para conservar los datos en una base de datos (Oracle, H2).
El consumidor utiliza un tiempo de confirmación comprometida para evitar fdisk problemas de sincronización en la base de datos.
(las bases de datos de tipo H2 son asincrono commit por defecto y evitan ese problema) Logo la persistencia en el consumidor para mantener un registro del tamaño de la cola para estar seguro
es capaz de mantenerse al día con el productor. Funciona bastante bien para mí

0

MapDB proporciona HashMaps/TreeMaps de alto rendimiento que se conservan en el disco. Es una biblioteca única que puedes incluir en tu programa Java.

0

Chronicle Map es una implementación ConcurrentMap que almacena las claves y los valores fuera del montón, en un archivo mapeado en la memoria. Por lo tanto, tiene persistencia en el reinicio de JVM.

ChronicleMap.get() es consistentemente más rápido que 1 nosotros, a veces tan rápido como 100 ns/operación. Es la solución the fastest en la clase.