Redis (Remote Dictionary Server) to niezwykle popularny magazyn kluczy i wartości w pamięci, który zapewnia również opcjonalną trwałość, partycjonowanie, replikację i wiele innych funkcji. Jest to obecnie najpopularniejsza baza danych klucz-wartość i jest znana ze swojej prostoty, niskiego zużycia pamięci i niskiej krzywej uczenia się. Redis jest również nazywany serwerem struktury danych i obsługuje operacje atomowe na strukturach danych, takich jak skróty, listy, zestawy, posortowane zestawy, mapy bitowe i hiperlogi. W tym poście przyjrzymy się ustawionemu typowi danych dostarczonemu przez Redis wraz z jego użyciem i rzeczywistymi przypadkami użycia.
Zestawy Redis
Zestawy Redis to nieuporządkowane kolekcje ciągów (ciąg znaków to podstawowa wartość Redis, która może zawierać prawie wszystko), które zapewniają stałe dodawanie, usuwanie i sprawdzanie członkostwa. Redis obsługuje również dość szybkie operacje łączenia, przecinania i odejmowania między zestawami. Zgodnie z oczekiwaniami nie zezwala na powtarzanie wartości.
Oto kilka przykładów zestawów Redis w akcji z redis-cli . Oto podsumowanie kluczowych reprezentacji w poniższym przykładzie:
- users:all reprezentuje zbiór wszystkich użytkowników zarejestrowanych na stronie internetowej.
- users:actv reprezentuje aktywnych użytkowników.
- users:inactv reprezentuje nieaktywnych użytkowników (użytkowników, którzy przez jakiś czas nie odwiedzali witryny).
# sadd key member [member ...] : add members to a set 127.0.0.1:6379> sadd users:all 11 12 13 14 15 Rocket Pocket Socket (integer) 8 127.0.0.1:6379> type users:all set # smembers key: get all members of a set 127.0.0.1:6379> smembers users:all 1) "Pocket" 2) "11" 3) "Socket" 4) "13" 5) "14" 6) "Rocket" 7) "12" 8) "15" # sismember key member: is the given value a member of the set? 127.0.0.1:6379> sismember users:all 00 (integer) 0 127.0.0.1:6379> sismember users:all 11 (integer) 1 127.0.0.1:6379> sismember users:all Socket (integer) 1 127.0.0.1:6379> sadd users:inactv 11 12 13 (integer) 3 # sinter key [key ...]: Intersection of multiple sets # Similar: sinterstore stores the result of intersection of sets to a new set 127.0.0.1:6379> sinter users:all users:inactv 1) "11" 2) "12" 3) "13" # scard key: cardinality of the set i.e. number of members present in the set 127.0.0.1:6379> scard users:all (integer) 8 # sdiff key [key ...] : Subtract multiple sets # Similar: sdiffstore: subtract and store result in a new destination set 127.0.0.1:6379> sdiff users:all 1) "Pocket" 2) "11" 3) "Socket" 4) "13" 5) "14" 6) "12" 7) "Rocket" 8) "15" 127.0.0.1:6379> sdiff users:all users:inactv 1) "14" 2) "Pocket" 3) "Rocket" 4) "Socket" 5) "15" # sdiffstore destination key [key ...] 127.0.0.1:6379> sdiffstore users:actv users:all users:inactv (integer) 5 127.0.0.1:6379> smembers users:actv 1) "14" 2) "Pocket" 3) "Rocket" 4) "Socket" 5) "15" 127.0.0.1:6379> sdiff users:all users:actv users:inactv (empty list or set) # smove source destination member: move a member from source set to destination. 127.0.0.1:6379> smove users:inactv users:actv 11 (integer) 1 127.0.0.1:6379> smembers users:actv 1) "Pocket" 2) "11" 3) "Socket" 4) "14" 5) "Rocket" 6) "15"
Inne ważne polecenia zestawu to:
- SUNION – ustaw związek
- SPOP – losowo usuń element
- SREM – usuń jeden lub więcej elementów
Pełną listę powiązanych poleceń Redis można znaleźć tutaj.
Redis wewnętrzne
Redis wewnętrznie przechowuje zestawy jako słowniki. Słowniki w Redis są zaimplementowane jako tablice mieszające, które używają funkcji mieszającej MurmurHash2 i powiększają się dzięki stopniowej zmianie rozmiaru. Kolizje skrótów są obsługiwane przez tworzenie łańcuchów. Zbiory mają specjalne kodowanie dla małych zbiorów, gdy wszyscy członkowie zbioru mają podstawę 10 w zakresie # 64-bitowych liczb całkowitych ze znakiem zwanych IntSets. Jest to zasadniczo posortowana tablica liczb całkowitych. Wyszukiwanie w tablicy odbywa się za pomocą wyszukiwania binarnego. Oczywiście ta implementacja jest wydajna dla bardzo małych zestawów. Rozmiar, do którego używane jest to kodowanie, jest regulowany przez set-max-intset-entries parametr konfiguracyjny. Wartość domyślna to 512. Dobry opis wewnętrznych struktur danych używanych przez Redis można znaleźć tutaj.
Aplikacje Redis
Oto mała lista kilku możliwych aplikacji Redis Set:
- Jako zestaw może służyć do śledzenia unikalnych elementów:
- Wszystkie unikalne adresy IP odwiedzające Twoją witrynę.
- Wszystkie unikalne instancje zadań aktualnie w danym stanie itp.
- Ponownie, jako zestaw, może być użyty do oznaczenia jako „należy do” lub podobnej relacji:
- Wszystkie SKU należące do określonej kategorii.
- Wszystkie obiekty z określonym znacznikiem itp.
- Zbiory mogą być używane tylko do łączenia relacji, tj. łączenie/przecięcie/odejmowanie zbiorów:
- Wszystkie kody SKU należące do kategorii koszulek, ale nie do podkategorii golfów.
Weźmy przykład z życia i zbadajmy zestaw powiązanych przypadków użycia.
Profil wizualny dla Twojego sklepu z e-bookami
Załóżmy, że jesteś właścicielem bardzo dużej księgarni internetowej, w której znajdują się miliony tytułów. Twoja podstawowa baza danych to MongoDB i działa ona całkiem dobrze w większości przypadków użycia z prawidłowym wykorzystaniem indeksowania, shardingu itp. Oto częściowy schemat dokumentu DB dla książek kolekcje:
... sku: SKU, pid: Product ID, title: String, auth: String, pub: String, isbn: ISBN, edition: Int, price: Float, rating: Float, cats: [String, String ...], tags: [String, String ...], ...
Tworzysz również transakcje w kolekcji o nazwie txns który może wyglądać tak:
txnid: TxnID, cid: CustomerID, amnt: Float, curr: Currency, sku: [sku1, sku2, ...], time: TimeStamp, ...
I zbiór widoków o nazwie widoki:
time: TimeStamp, # daily aggregated cid: CustomerID, sku: [sku1, sku2, ...], ...
Oczywiście jest to bardzo uproszczony przykład, który zawiera szerokie założenia. Naszym zamiarem jest pokazanie przykładu zestawu Redis w (niemal) rzeczywistym scenariuszu.
Ok, teraz jako kierownik sklepu potrzebujesz narzędzia Visual Profiler do analizowania relacji i zachowań klientów w różnych kategoriach. Na przykład:
- Jaka jest najpopularniejsza kategoria?
- Czy osoby oglądające lub kupujące science fiction również patrzą na literaturę faktu?
Chcesz mieć możliwość robienia tego w czasie rzeczywistym, tj. interfejs użytkownika profilera będzie zaznaczał pola, przyciski, które pozwalają zmieniać parametry i wyświetlać wyniki (prawie) natychmiast.
Wykonywanie takich operacji na MongoDB będzie wiązało się z wykonywaniem dość skomplikowanych zapytań, aby połączyć różne kategorie, tagi i inne dane, na których możesz się zainteresować. Z zestawem roboczym, który nie mieści się w pamięci, nie byłyby to najszybsze operacje. Na przykład:
- Znalezienie wszystkich sprzedanych dzisiaj książek, które były fikcją, ale nie Science Fiction, będzie wymagać zapytania txn zbiór dzisiejszych transakcji. Następnie iteruje po SKU w celu zebrania ich kategorii, a następnie wykonuje operacje $in/$nin.
Zobaczmy, jak sobie z tym poradzimy, wprowadzając Redis do miksu. Na koniec każdego dnia codzienne zaplanowane zadania mogą być uruchamiane przez te kolekcje MongoDB w celu tworzenia zestawów Redis. Rodzaj zestawów, które chcesz utworzyć, będzie zależał od rodzaju filtrów, które chcesz obsługiwać w swoim interfejsie. Załóżmy na przykład, że chcesz obsługiwać zapytania związane z kategoriami, będziemy chcieli utworzyć zestawy takie jak:
cat:type:catID cat:sku:fiction cat:sku:nonfiction cat:sku:scfiction cat:sku:history cat:sku:milhistory cat:sku:military ... cat:cid:fiction cat:cid:nonfiction cat:cid:scfiction cat:cid:history cat:cid:milhistory cat:cid:military ...
Zestawy cat:sku:* będą zawierać kody SKU sprzedanych/obejrzanych dzisiaj książek w tej kategorii. Podobnie cat:cid:* będzie zawierać CID klientów, którzy kupili/sprzedali książki w tej kategorii. Przykładowe pytania, na które możemy odpowiedzieć za pomocą tych zestawów to:
- Klienci (lub liczba klientów), którzy dzisiaj oglądali/kupili książki Fiction (jedna kategoria):członkowie cat:cid:fiction
- Klienci, którzy oglądali/kupili historię, ale nie historię wojskową dzisiaj:sdiff cat:cid:history cat:cid:milhistory
- (Liczba) Książek sprzedanych dzisiaj, które były science fiction i wojskowymi, czyli wojskowymi science fiction:sinter cat:sku:scfiction cat:sku:military
- Dowolna liczba takich operacji łączenia, przecięcia i różnicy, na których Ci zależy.
To samo w sobie daje nam bardzo potężne możliwości zapytań. Dodajmy więcej zestawów! Powiedzmy, że tworzymy dodatkowe zestawy na podstawie ocen książek. Na przykład:
rat:sku:5str: Set of books with ratings > 4.5 rat:sku:4str: Set of books with ratings > 3.5 && <= 4.5 rat:sku:3str: ... rat:sku:2str: ... ... rat:cid:5str: Set of customer who bought books with ratings as mentioned above. rat:cid:4str: ... ..
Wyposażony w te zestawy, możesz teraz szybko znaleźć takie rzeczy, jak:
- książki beletrystyczne z 4 gwiazdkami i wyżej ocenione dzisiaj: sunionstore rat:sku:4strabv rat:sku:5str rat:sku:5str/sinter rat:sku:4strabv kot :sku:fikcja
- Klient, który w historii kupił co najmniej trzy gwiazdki:sunionstore rat:cid:5strabv rat:cid:3str rat:cid:5str rat:cid:5str/sinter cat:cid:historia szczur:cid:5strabv
Załóżmy teraz, że chcesz wysłać kupon rabatowy do wszystkich klientów, którzy kupili dzisiaj książkę o astrologii z oceną 2 lub niższą (jako przeprosiny za złe doświadczenia o konieczności przeczytania tej książki!). Możesz wyeksportować tę listę ID klienta wyślij i wyślij do aplikacji e-mail. Podobnie możesz utworzyć zestawy dla innych rzeczy, które możesz chcieć wyeksponować jako filtry w swoim Visual Profilerze, takich jak tagi, przedziały cenowe itp.
Zalety korzystania z zestawów Redis są tutaj oczywiste. Sklep in-memory zapewni naprawdę szybki dostęp, dzięki czemu frontend będzie zgrabny. Dodatkowo operacje na zestawach Redis są albo stałe, albo liniowe.
Wniosek
W tym poście przedstawiliśmy z przykładami jedną z najbardziej przydatnych struktur danych Redis:zestawy. Oto niektóre z naszych innych postów z serii struktur danych Redis:
- Hasze Redis
- Mapy bitowe Redis
- Zestawy Redis
- Posortowane zestawy ponownie