Indeksowanie za pomocą posortowanych zestawów Redis

Chciałbym uzyskać pewne opinie i sugestie dotyczące dwóch podejść, które rozważam w celu wdrożenia indeksów z możliwością wyszukiwania przy użyciu posortowanych zestawów Redis.

Sytuacja i cel

Obecnie mamy kilka tabel o wartości kluczowej, które przechowujemy w Cassandrze i dla których chcielibyśmy mieć indeksy. Na przykład jedna tabela zawierałaby rekordy ludzi, a tabela Cassandry miałaby jako klucz podstawowy identyfikator, a obiekt szeregowany jako wartość. Obiekt miałby pola takie jak imię, nazwisko, ostatnia aktualizacja i inne.

Chcemy mieć możliwość wyszukiwania, takiego jak „last_name = 'Smith' AND first_name> 'Joel'”, „last_name <'Aaronson” ”,„ last_name =' Smith 'AND first_name =' Winston '”i tak dalej . Wyszukiwania powinny dawać identyfikatory meczów, abyśmy mogli odzyskać obiekty od Cassandry. Myślę, że powyższe wyszukiwania można wykonać za pomocą pojedynczego indeksu, posortowanego leksykograficznie według last_name, first_name i last_updated. Jeśli potrzebujemy kilku wyszukiwań w innej kolejności (np. „First_name =„ Zeus ””), możemy mieć podobny indeks, który pozwalałby na taki indeks (np. First_name, last_updated).

Szukamy do tego Redis, ponieważ musimy być w stanie obsłużyć dużą liczbę zapisów na minutę. Przeczytałem kilka typowych sposobów sortowania zestawów Redis i wymyślę dwie możliwe implementacje:

Opcja 1: pojedynczy posortowany zestaw na indeks

Dla naszego indeksu według last_name, first_name, last_updated, mielibyśmy posortowany zestaw w Redis pod kluczowymi indeksami: people: last_name: first_name: last_updated, który zawierałby łańcuchy w formacie last_name: first_name: last_updated: id. Na przykład:

smith: joel: 1372761839.444: 0azbjZRHTQ6U8enBw6BJBw

(W przypadku separatora mogę użyć słowa „::” zamiast „:” lub czegoś innego, aby lepiej współpracować z porządkiem leksykograficznym, ale na razie zignorujmy to)

Wszystkie elementy uzyskają wynik 0, aby posortowany zestaw został posortowany leksykograficznie przez same łańcuchy. Jeśli następnie chcę wykonać zapytanie, takie jak „last_name =” smith ”I first_name <'bob” ”, musiałbym pobrać wszystkie elementy z listy, które pojawią się przed„ smith: bob ”.

O ile wiem, to podejście ma następujące wady:

Nie ma funkcji Redis, aby wybrać zakres na podstawie wartości ciągu. Ta funkcja, zwana ZRANGEBYLEX, została zaproponowana przez Salvatore Sanfilippo whttps://github.com/antirez/redis/issues/324 , ale nie jest zaimplementowany, więc musiałbym znaleźć punkty końcowe, używając wyszukiwań binarnych i samemu uzyskać zakres (być może używając Lua lub na poziomie aplikacji z Pythonem, który jest językiem, którego używamy do uzyskania dostępu do Redis).Jeśli chcemy uwzględnić czas życia dla wpisów indeksu, wydaje się, że najprostszym sposobem na to będzie posiadanie regularnie zaplanowanego zadania, które przechodzi przez cały indeks i usuwa przeterminowane elementy.

Opcja 2: małe posortowane zestawy posortowane według last_updated

Podejście to byłoby podobne, gdybyśmy nie mieli wielu, mniejszych, posortowanych zestawów, z których każdy miałby wartość podobną do czasu, taką jak last_updated dla wyników. Na przykład dla tej samej nazwy last_name, first_name, last_updated index, mielibyśmy posortowany zestaw dla każdej kombinacji last_name, first_name. Na przykład kluczem mogą być indeksy: ludzie: last_name = smith: first_name = joel, i będzie miał wpis dla każdej osoby, którą nazwaliśmy Joel Smith. Każda pozycja miałaby nazwę id i jej wynik jako wartość last_updated. Na przykład.:

wartość: 0azbjZRHTQ6U8enBw6BJBw; wynik: 1372761839.444

Głównymi zaletami tego rozwiązania są (a) wyszukiwania, w których wiemy, że wszystkie pola oprócz last_updated byłyby bardzo łatwe, i (b) wdrożenie czasu do uruchomienia byłoby bardzo łatwe przy użyciu ZREMRANGEBYSCORE.

Wadą, która wydaje mi się bardzo duża, jest:

Wydaje się, że zarządzanie i wyszukiwanie w ten sposób jest o wiele bardziej złożone. Na przykład, potrzebowalibyśmy indeksu, aby śledzić wszystkie jego klucze (w przypadku, na przykład, chcemy oczyścić w pewnym momencie) i zrobić to w sposób hierarchiczny. Wyszukiwanie takie jak „last_name <'smith'” wymagałoby najpierw spojrzenia na listę wszystkich nazwisk, aby znaleźć te, które pojawiają się przed kowalem, a następnie dla każdego z tych, którzy oglądają wszystkie imiona, które zawiera, a następnie dla każdego z nich pobieranie wszystkich przedmiotów z posortowanego zestawu. Innymi słowy, wiele elementów do rozbudowy i zmartwień.

Zawijanie

Wydaje mi się więc, że pierwsza opcja byłaby lepsza, pomimo jej wad. Byłbym bardzo wdzięczny za wszelkie opinie dotyczące tych dwóch lub innych możliwych rozwiązań (nawet jeśli powinniśmy użyć czegoś innego niż Redis).

questionAnswers(3)

yourAnswerToTheQuestion