Jedną z rzeczy, które często dezorientują użytkowników zaznajomionych z innymi bazami danych, gdy próbują Redis, jest brak wglądu w bazę danych:nie ma zestawu tabel ani kolekcji do widzisz, po prostu zwykła, płaska przestrzeń klucza, która może (potencjalnie) mieć miliony kluczy. Zdolność do taniej iteracji w tej przestrzeni klucza staje się zatem bardzo ważna dla zapoznania się z zawartością bazy danych.
Iterowanie w przestrzeni klucza Redis ma inne ważne przypadki użycia, a kilka, które przychodzą na myśl, to:
- wyrzucanie śmieci lub czyszczenie kluczy pasujących do określonego wzorca
- przenoszenie danych i zmiany schematu lub przenoszenie określonego zestawu kluczy do innej struktury danych
- debugowanie, próbkowanie danych, poprawki danych lub znajdowanie i naprawianie wszystkich kluczy, które zostały pomieszane przez ostatnią zmianę
W tym poście zagłębimy się w różne opcje iteracji przestrzeni kluczowych dostępnych w Redis.
O(N) Iteratory:KLUCZE
Polecenie Redis KEYS zwraca wszystkie klucze w bazie danych, które pasują do wzorca (lub wszystkie klucze w przestrzeni kluczy). Podobne polecenia do pobierania wszystkich pól przechowywanych w hashu to HGETALL i do pobierania wszystkich członków SMEMBERS. Same klucze w Redis są przechowywane w słowniku (tzw. tablica mieszająca). Polecenie KEYS działa poprzez iterację tego słownika i wysyłanie wszystkiego, co pasuje do wzorca, jako pojedynczej odpowiedzi Array. Pozostałe polecenia działają podobnie.
Wydajność takiej operacji zależy od wielkości kolekcji, czyli O(N). Dlatego używanie KEYS jest zdecydowanie odradzane w środowiskach produkcyjnych z dużą liczbą kluczy. Redis jest jednowątkowy, zostaje zablokowany podczas tej iteracji, blokując w ten sposób inne operacje. Dlatego KLUCZE powinny być używane tylko do debugowania i innych specjalnych okazji, w których wydajność nie jest problemem (np. gdy baza danych została przełączona w tryb offline w celu zastosowania poprawki danych). Inną ważną rzeczą do zapamiętania na temat tego algorytmu jest to, że wysyła wszystkie pasujące klucze razem jako pojedynczą odpowiedź. Może to być niezwykle wygodne, gdy przestrzeń na klucze jest mała, ale spowoduje wiele problemów na dużej przestrzeni na klucze. KEYS jest jednak ulubioną komendą wśród programistów we własnych środowiskach programistycznych.
KLUCZE w akcji:
127.0.0.1:6379[1]> MSET one 1 two 2 three 3 four 4 OK # All the keys 127.0.0.1:6379[1]> keys * 1) "four" 2) "three" 3) "two" 4) "one" # keys that begin with the letter 't' 127.0.0.1:6379[1]> keys t* 1) "three" 2) "two" # keys that have a 'ee' in them 127.0.0.1:6379[1]> keys *ee* 1) "three"
Iteratory oparte na kursorach:SKANOWANIE
SCAN i jego siostrzane polecenia, SSCAN (dla zestawów), HSCAN (dla skrótów) i ZSCAN (dla posortowanych zestawów) zapewniają podejście oparte na kursorze do iteracji struktur danych Redis. Są dostępne w Redis od 2.8.0.
Klucze są zwracane w przyrostowych iteracjach z gwarancją stałego czasu dla każdej iteracji. Kursor (w tym przypadku jest to liczba całkowita) jest zwracany, gdy iteracje są inicjowane i zwracany jest zaktualizowany kursor i każda iteracja. Cykl iteracji rozpoczyna się, gdy kursor jest ustawiony na 0 w żądaniu SCAN i kończy się, gdy kursor zwracany przez serwer ma wartość 0. Ze względu na niuanse architektury Redis i implementacji algorytmu kursora, oto niektóre osobliwości tego podejścia:
- Pełna iteracja zawsze pobiera wszystkie elementy, które były obecne w kolekcji od początku do końca pełnej iteracji.
- Pełna iteracja nigdy nie zwraca żadnego elementu, który NIE był obecny w kolekcji od początku do końca pełnej iteracji.
- Dany element może być zwracany wielokrotnie. W przypadku zduplikowanych elementów zależy od aplikacji
- Elementy, które nie były stale obecne w kolekcji podczas pełnej iteracji, mogą zostać zwrócone lub nie:jest to niezdefiniowane.
- Liczba elementów zwracanych podczas każdego zliczania jest różna i może również wynosić 0. Jednak iteracja nie jest zakończona, dopóki serwer nie zwróci wartości kursora równej 0.
- LICZBA opcja może służyć do ograniczenia liczby elementów zwracanych w każdej iteracji. Wartość domyślna to 10. Jednak jest to tylko sugestia i nie jest wymuszane we wszystkich przypadkach. Wartość COUNT można zmienić podczas każdego wywołania iteracji.
- DOPASUJ opcja pozwala na określenie wzorców, tak jak pozwala na to polecenie KLAWISZE.
- Implementacja kursora jest całkowicie bezstanowa po stronie serwera. Dzięki temu (potencjalnie) nieskończone iteracje mogą się rozpoczynać równolegle. Ponadto nie ma wymagań dotyczących zapewnienia, że iteracja będzie kontynuowana do końca i może zostać zatrzymana w dowolnym momencie.
Pomimo swoich osobliwości, SCAN jest bardzo użytecznym poleceniem i właściwym poleceniem do wyboru dla iteracji w przestrzeni klawiszy w większości przypadków użycia.
SKANUJ jest bardzo przydatnym poleceniem i właściwym poleceniem, które można wybrać w przypadku iteracji spacji z klawiszami w #RedisClick To TweetSKANOWANIE w akcji
127.0.0.1:6379[1]> flushdb OK 127.0.0.1:6379[1]> keys * (empty list or set) 127.0.0.1:6379[1]> debug populate 33 OK 127.0.0.1:6379[1]> scan 0 COUNT 5 1) "4" 2) 1) "key:1" 2) "key:9" 3) "key:13" 4) "key:29" 5) "key:23" 127.0.0.1:6379[1]> scan 4 1) "42" 2) 1) "key:24" 2) "key:28" 3) "key:18" 4) "key:16" 5) "key:12" 6) "key:2" 7) "key:6" 8) "key:31" 9) "key:27" 10) "key:19" 127.0.0.1:6379[1]> scan 42 1) "9" 2) 1) "key:3" 2) "key:4" 3) "key:20" 4) "key:8" 5) "key:32" 6) "key:5" 7) "key:26" 8) "key:10" 9) "key:21" 10) "key:14" 127.0.0.1:6379[1]> scan 9 COUNT 100 1) "0" 2) 1) "key:25" 2) "key:30" 3) "key:22" 4) "key:17" 5) "key:15" 6) "key:0" 7) "key:11" 8) "key:7"
Pod maską
Algorytm, którego używa do skanowania SCAN (i jego siostrzane polecenia) jest intrygujący i prowadzi do niektórych cech polecenia, które opisaliśmy powyżej. Antirez opisał to na wysokim poziomie w swoim blogu i jest to wyjaśnione (nieco lepiej) w komentarzach nad implementacją (funkcja dictScan). Szczegółowy opis sprawi, że ten post będzie zbyt długi, więc podam wystarczająco dużo opisu, aby jego konsekwencje były oczywiste.
- Większość struktur danych Redis jest wewnętrznie reprezentowana jako słowniki (przynajmniej częściowo w przypadku posortowanych zestawów). Są one zaimplementowane jako tablice mieszające o mocy dwóch rozmiarów z łańcuchem dla kolizji. Wyzwaniem w pisaniu iteracyjnego algorytmu opartego na kursorze jest możliwość radzenia sobie z powiększaniem i zmniejszaniem wartości skrótu bez poświęcania zasad prostoty (interfejsu API) i szybkości Redis.
- SCAN zasadniczo skanuje kilka wiader mieszających w każdej iteracji i zwraca elementy pasujące do wzorca w nich. Ponieważ patrzy tylko na ustaloną listę segmentów, niektóre iteracje mogą w ogóle nie zwracać żadnych wartości.
- Kursor, który jest zwracany, jest w zasadzie przesunięciem do iterowanej tablicy mieszającej. Zajmuje się powiększaniem i zmniejszaniem tablic mieszających (tj. przehaszowaniem) poprzez sprytne manipulowanie bitami przesunięcia wyższego poziomu przy jednoczesnym zwiększeniu przesunięcia wraz z właściwościami tablicy mieszającej. Implikacje z tego podejścia są takie, że nowe elementy dodane podczas iteracji mogą, ale nie muszą być zwracane. Jednak sam kursor nie musiałby uruchamiać się ponownie po zmianie rozmiaru tablicy mieszającej.
- Dane wiadro musi zostać odwiedzone tylko raz, a wszystkie jego klucze muszą zostać zwrócone za jednym razem. To znowu ma na celu upewnienie się, że zmiana rozmiaru skrótu (tj. ponowne haszowanie) nie komplikuje postępu iteracji. Jednak prowadzi to do tego, że argument COUNT nie jest ściśle egzekwowalny.
- Ponieważ powyższe podejście jest całkowicie bezstanowe po stronie serwera, oznacza to w zasadzie, że iteracje można zatrzymać lub równolegle uruchomić ogromną liczbę iteracji bez zwiększonego zużycia pamięci.
Podsumowanie
Na wysokim poziomie dostępne są dwie opcje do iteracji w przestrzeni klucza Redis:
- Użyj KLAWISZY, gdy wydajność nie jest problemem lub gdy przestrzeń na klucze jest rozsądna.
- W pozostałych przypadkach używaj funkcji SKANUJ.
Czy wiesz, że obsługujemy teraz hosting dla Redis™*? Uzyskaj w pełni zarządzany hosting dla Redis™ w bezpiecznym miejscu na własnym koncie w chmurze i wykorzystaj kredyty AWS/Azure do wdrożeń Redis™.