Indexación utilizando conjuntos ordenados de Redis

Me gustaría recibir algunos comentarios y sugerencias con respecto a dos enfoques que estoy considerando para implementar índices de búsqueda utilizando los conjuntos ordenados de Redis.

Situación y objetivo.

Actualmente tenemos algunas tablas de valores clave que estamos almacenando en Cassandra y para las cuales nos gustaría tener índices. Por ejemplo, una tabla contendría registros de personas, y la tabla de Cassandra tendría id como su clave principal y el objeto serializado como el valor. El objeto tendría campos como el primer nombre, el último nombre, la última actualización y otros.

Lo que queremos es poder realizar búsquedas como "last_name = 'Smith' AND first_name> 'Joel'", "last_name <'Aaronson'", "last_name = 'Smith' AND first_name = 'Winston'", etc. . Las búsquedas deben proporcionar los identificadores de coincidencias para que podamos recuperar los objetos de Cassandra. Estoy pensando que las búsquedas anteriores se podrían hacer con un solo índice, ordenado lexicográficamente por last_name, first_name y last_updated. Si necesitamos algunas búsquedas utilizando un orden diferente (por ejemplo, "first_name = 'Zeus'"), podemos tener un índice similar que permitiría esas (por ejemplo, first_name, last_updated).

Estamos considerando usar Redis para esto, porque tenemos que ser capaces de manejar una gran cantidad de escrituras por minuto. He leído algunas formas comunes en que se utilizan los conjuntos ordenados de Redis, y se presentan dos posibles implementaciones:

Opción 1: un único conjunto ordenado por índice

Para nuestro índice por last_name, first_name, last_updated, tendríamos un conjunto ordenado en Redis bajo los índices clave: personas: last_name: first_name: last_updated, que contendría cadenas con el formato last_name: first_name: last_updated: id. Por ejemplo:

smith: joel: 1372761839.444: 0azbjZRHTQ6U8enBw6BJBw

(Para el separador podría usar '::' en lugar de ':' u otra cosa para trabajar mejor con el orden lexicográfico, pero ignoremos eso por ahora)

A todos los elementos se les otorgará una puntuación de 0, de modo que el conjunto ordenado solo se clasifique lexicográficamente por las propias cadenas. Si luego quiero hacer una consulta como "last_name = 'smith' AND first_name <'bob'", necesitaría obtener todos los elementos de la lista que aparecen antes de 'smith: bob'.

Hasta donde puedo decir, existen los siguientes inconvenientes de este enfoque:

No hay una función de Redis para seleccionar un rango basado en el valor de la cadena. Esta característica, llamada ZRANGEBYLEX, ha sido propuesta por Salvatore Sanfilippo enhttps://github.com/antirez/redis/issues/324 , pero no está implementado, así que tendría que encontrar los puntos finales utilizando búsquedas binarias y obtener el rango yo mismo (tal vez utilizando Lua, o en el nivel de aplicación con Python, que es el lenguaje que estamos usando para acceder a Redis).Si queremos incluir un tiempo de vida para las entradas de índice, parece que la forma más sencilla de hacerlo sería tener una tarea programada regularmente que pase por todo el índice y elimine los elementos caducados.

Opción 2: pequeños conjuntos ordenados, ordenados por last_updated

Este enfoque sería similar, excepto que tendríamos muchos conjuntos ordenados, más pequeños, y cada uno de ellos tendría un valor similar al tiempo, como last_updated para las puntuaciones. Por ejemplo, para el mismo último nombre, primer nombre, último índice actualizado, tendríamos un conjunto ordenado para cada combinación de último nombre, primer nombre. Por ejemplo, la clave podría ser los índices: personas: apellido_ smith: primer nombre = joel, y tendría una entrada para cada persona a la que hemos llamado Joel Smith. Cada entrada tendría como nombre el id y su puntaje el valor last_updated. P.ej.:

valor: 0azbjZRHTQ6U8enBw6BJBw; puntuación: 1372761839.444

Las principales ventajas de esto son (a) búsquedas donde sabemos que todos los campos excepto last_updated serían muy fáciles, y (b) implementar un tiempo de vida sería muy fácil, usando ZREMRANGEBYSCORE.

El inconveniente, que me parece muy grande, es:

Parece que hay mucha más complejidad en la gestión y búsqueda de esta manera. Por ejemplo, necesitaríamos el índice para realizar un seguimiento de todas sus claves (en caso de que, por ejemplo, deseamos limpiar en algún momento) y hacerlo de forma jerárquica. Una búsqueda como "last_name <'smith'" requeriría primero mirar la lista de todos los apellidos para encontrar aquellos que vienen antes de smith, luego para cada uno de los que miran todos los primeros nombres que contiene, y luego para cada uno de ellos obteniendo todos los artículos de su conjunto ordenado. En otras palabras, muchos componentes para construir y preocuparse.

Terminando

Así que me parece que la primera opción sería mejor, a pesar de sus inconvenientes. Apreciaría mucho cualquier comentario con respecto a estas dos u otras posibles soluciones (incluso si es que deberíamos usar algo que no sea Redis).

Respuestas a la pregunta(3)

Su respuesta a la pregunta