Indexando usando conjuntos ordenados Redis

Gostaria de obter alguns comentários e sugestões sobre duas abordagens que estou considerando para implementar índices pesquisáveis ​​usando conjuntos de classificação Redis.

Situação e objetivo

Atualmente, temos algumas tabelas de valores-chave que estamos armazenando no Cassandra e para as quais gostaríamos de ter índices. Por exemplo, uma tabela conteria registros de pessoas e a tabela do Cassandra teria o id como sua chave primária e o objeto serializado como o valor. O objeto teria campos como first_name, last_name, last_updated e outros.

O que queremos é poder fazer pesquisas como "last_name = 'Smith' e first_name> 'Joel'", "last_name <'Aaronson'", "last_name = 'Smith' e first_name = 'Winston'" e assim por diante . As pesquisas devem produzir os ids das correspondências para que possamos recuperar os objetos da Cassandra. Estou pensando que as pesquisas acima poderiam ser feitas com um único índice, classificadas lexicograficamente por last_name, first_name e last_updated. Se precisarmos de algumas pesquisas usando uma ordem diferente (por exemplo, "first_name = 'Zeus'"), poderemos ter um índice semelhante que permita essas (por exemplo, first_name, last_updated).

Estamos pensando em usar o Redis para isso, porque precisamos ser capazes de lidar com um grande número de gravações por minuto. Eu li em algumas maneiras comuns que os conjuntos de classificação Redis são usados, e desenvolvo duas implementações possíveis:

Opção 1: um único conjunto classificado por índice

Para nosso índice por last_name, first_name, last_updated, teríamos um conjunto classificado no Redis sob os índices de chave: people: last_name: first_name: last_updated, que conteria strings com o formato last_name: first_name: last_updated: id. Por exemplo:

smith: joel: 1372761839.444: 0azbjZRHTQ6U8enBw6BJBw

(Para o separador eu poderia usar '::' ao invés de ':' ou algo mais para funcionar melhor com a ordenação lexicográfica, mas vamos ignorar isso por enquanto)

Todos os itens receberiam pontuação 0 para que o conjunto classificado fosse classificado lexicograficamente pelas próprias seqüências. Se eu quiser fazer uma consulta como "last_name = 'smith' AND first_name <'bob'", eu precisaria obter todos os itens da lista que vieram antes de 'smith: bob'.

Tanto quanto eu posso dizer, existem os seguintes inconvenientes para esta abordagem:

Não há função Redis para selecionar um intervalo com base no valor da string. Este recurso, chamado ZRANGEBYLEX, foi proposto por Salvatore Sanfilippo emhttps://github.com/antirez/redis/issues/324 , mas não está implementado, então eu teria que encontrar os endpoints usando buscas binárias e obter o intervalo eu mesmo (talvez usando Lua, ou no nível do aplicativo com Python, que é a linguagem que estamos usando para acessar o Redis).Se quisermos incluir um tempo de vida para entradas de índice, parece que a maneira mais simples de fazê-lo seria ter uma tarefa agendada regularmente que percorra todo o índice e remova itens expirados.

Opção 2: pequenos conjuntos classificados, classificados por last_updated

Essa abordagem seria semelhante, exceto pelo fato de termos muitos conjuntos menores, classificados, com cada um tendo um valor semelhante ao tempo, como last_updated para as pontuações. Por exemplo, para o mesmo last_name, first_name, last_updated index, teríamos um conjunto classificado para cada combinação last_name, first_name. Por exemplo, a chave pode ser índices: people: last_name = smith: first_name = joel e teria uma entrada para cada pessoa que chamamos de Joel Smith. Cada entrada teria como seu nome o id e sua pontuação o valor last_updated. Por exemplo.:

valor: 0azbjZRHTQ6U8enBw6BJBw; Pontuação: 1372761839.444

As principais vantagens para isso são (a) pesquisas onde sabemos que todos os campos, exceto last_updated, seriam muito fáceis, e (b) implementar um time-to-live seria muito fácil, usando o ZREMRANGEBYSCORE.

A desvantagem, que parece muito grande para mim é:

Parece haver muito mais complexidade em gerenciar e pesquisar dessa maneira. Por exemplo, precisaríamos que o índice rastreasse todas as suas chaves (no caso, por exemplo, queremos limpá-las em algum momento) e fazer isso de maneira hierárquica. Uma busca como "last_name <'smith'" exigiria primeiro olhar a lista de todos os sobrenomes para encontrar aqueles que vêm antes de smith, então para cada um daqueles que procura por todos os primeiros nomes que contém, então para cada um daqueles obtendo todos os itens de seu conjunto classificado. Em outras palavras, muitos componentes se acumulam e se preocupam.

Empacotando

Então, parece-me que a primeira opção seria melhor, apesar de suas desvantagens. Eu apreciaria muito qualquer feedback sobre essas duas ou outras possíveis soluções (mesmo que elas devam usar algo diferente do Redis).

questionAnswers(3)

yourAnswerToTheQuestion