sql - servidor - ejemplo de base de datos en memoria
Fuera de proceso en la tabla de base de datos de memoria que admite consultas para almacenamiento en caché de alta velocidad (7)
Tengo una tabla SQL a la que se accede continuamente pero que cambia muy raramente.
La tabla está particionada por UserID y cada usuario tiene muchos registros en la tabla.
Quiero guardar los recursos de la base de datos y acercar esta tabla a la aplicación en algún tipo de memoria caché.
En el proceso, el almacenamiento en caché requiere demasiada memoria, por lo que debe ser externo a la aplicación.
Las tiendas de Key Value como Redis están resultando ineficientes debido a la sobrecarga de serializar y deserializar la tabla desde y hacia Redis.
Estoy buscando algo que pueda almacenar esta tabla (o particiones de datos) en la memoria, pero permítame consultar solo la información que necesito sin serializar y deserializar grandes bloques de datos para cada lectura.
¿Hay algo que proporcione fuera de proceso en la tabla de la base de datos de memoria que admita consultas para el almacenamiento en caché a alta velocidad?
La búsqueda ha demostrado que Apache Ignite podría ser una opción posible, pero estoy buscando sugerencias más informadas.
Como dijo @for_stack, Hash
será muy adecuado para su caso.
usted dijo que cada usuario tiene muchas filas en db indexadas por user_id
y tag_id
. Así es que (user_id, tag_id) especifican de forma única una fila. Cada fila es funcional depende de esta tupla, puede usar la tupla como la HASH KEY.
Por ejemplo, si desea guardar la fila (user_id, tag_id, username, age) cuyos valores son ("123456", "FDSA", "gsz", 20) en redis, puede hacer esto:
HMSET 123456:FDSA username "gsz" age 30
Cuando desee consultar el nombre de usuario con user_id y tag_id, puede hacer lo siguiente:
HGET 123456:FDSA username
Por lo tanto, cada Hash Key será una combinación de user_id
y tag_id
, si desea que la clave sea más fácil de leer, puede agregar una cadena de prefijo como "USERINFO". Por ejemplo: USERINFO:123456:FDSA
.
PERO si desea consultar solo con un user_id y obtener todas las filas con este user_id, este método anterior no será suficiente.
Y podrías construir los índices secundarios en redis para tu HASH.
como se dijo anteriormente, usamos user_id:tag_id
como clave HASH. Porque puede apuntar puntos únicos a una fila. Si queremos consultar todas las filas sobre un user_id.
Podríamos usar un sorted set
para crear una indexación secundaria para indexar en qué Hashes almacena la información sobre este user_id.
Podríamos agregar esto en SortedSet:
ZADD user_index 0 123456:FDSA
Como se indicó anteriormente, establecemos el member
en la string of HASH key
y establecemos el score
en 0. Y la regla es que debemos establecer todo el puntaje en este zset en 0 y luego podríamos usar el orden lexicográfico para hacer una consulta de rango. Consulte zrangebylex .
Por ejemplo, queremos obtener todas las filas sobre user_id 123456,
ZRANGEBYLEX user_index [123456 (123457
Devolverá toda la clave HASH cuyo prefijo es 123456, y luego usaremos esta cadena como clave HASH y hget o hmget para recuperar la información que deseamos.
[
significa inclusivo, y (
significa exclusivo. ¿Y por qué usamos 123457
? Es obvio. Entonces, cuando queremos obtener todas las filas con un ID de usuario, deberíamos especificar el límite superior para hacer que el valor ascii del carácter más a la izquierda de la cadena del ID de usuario más 1.
Más sobre el índice lex puede consultar el artículo que mencioné anteriormente.
Con solo 6 principios (que he recopilado here ), es muy fácil para una persona con mentalidad de SQL adaptarse al enfoque de Redis. En pocas palabras son:
- Lo más importante es que, no tengas miedo de generar muchos pares clave-valor. Así que siéntase libre de almacenar cada fila de la tabla en una clave diferente.
- Usar el tipo de datos del mapa hash de Redis
- Nombre de clave de formulario a partir de los valores de clave principal de la tabla mediante un separador (como ":")
- Almacena los campos restantes como un hash
- Cuando desee consultar una sola fila, forme la clave directamente y recupere sus resultados
- Cuando desee consultar un rango, use carácter salvaje "*" hacia su clave. Pero tenga en cuenta que las claves de escaneo interrumpen otros procesos de Redis. Así que usa este método si realmente tienes que hacerlo.
El enlace solo da un ejemplo de tabla simple y cómo modelarlo en Redis. Siguiendo esos 6 principios, puedes seguir pensando como lo haces para las tablas normales. (Por supuesto, sin algunos conceptos no tan relevantes como CRUD, restricciones, relaciones, etc.)
Ignite es, de hecho, una solución posible para usted, ya que puede optimizar la sobrecarga de serialización / deserialización utilizando una representación binaria interna para acceder a los campos de los objetos. Puede consultar esta página de documentación para obtener más información: https://apacheignite.readme.io/docs/binary-marshaller
También se puede optimizar la sobrecarga de acceso al deshabilitar la opción de copia en lectura https://apacheignite.readme.io/docs/performance-tips#section-do-not-copy-value-on-read
La colocación de datos por ID de usuario también es posible con Ignite: https://apacheignite.readme.io/docs/affinity-collocation
Para una carga de trabajo con lectura dominante, el motor de MEMORY
MySQL debería funcionar bien (escribir DMLs en la tabla completa). De esta manera no necesita cambiar su lógica de recuperación de datos.
Alternativamente, si está de acuerdo con cambiar la lógica de recuperación de datos, Redis también es una opción. Para agregar a lo que @GuangshengZuo ha descrito, hay un ReJSON de ReJSON dinámica ReJSON Redis (para Redis 4+) que implementa el almacén de documentos sobre Redis. Puede relajar aún más los requisitos para organizar grandes estructuras de ida y vuelta a través de la red.
Puedes probar Apache mnemotécnica iniciada por Intel. Enlace - http://incubator.apache.org/projects/mnemonic.html . Es compatible con las características de serdeless.
el uso de Memcache y la combinación REDIS sobre MYSQL viene a la mente.
Dado que está fuera de proceso, tiene que hacer serialización y deserialización. El problema que le preocupa es cómo reducir el trabajo de serialización / deserción. Si utiliza el tipo STRING
Redis, NO PUEDE reducir estos trabajos.
Sin embargo, puede usar HASH
para resolver el problema: asignando su tabla de SQL a un HASH
.
Supongamos que tiene la siguiente tabla: person: id(varchar), name(varchar), age(int)
, puede tomar la id
persona como clave y el name
y la age
como campos. Cuando desee buscar el nombre de alguien, solo necesita obtener el campo de nombre (nombre de HGET person-id name
), otros campos no se deserializarán.