Pytania rekrutacyjne Redis

55 pytań — 20 odpowiedzi dostępnych od razu

Darmowy podgląd pytań rekrutacyjnych Redis pozwala odświeżyć wiedzę o magazynie danych używanym do cache, kolejek i szybkiego dostępu do informacji. Zawiera przykładowe pytania z puli 55 zagadnień.

Materiał obejmuje typy danych Redis, persystencję, replikację, wysoką dostępność oraz Pub/Sub. Pomaga przećwiczyć rozmowę o wydajności, niezawodności i zastosowaniu Redis w architekturze aplikacji.

Darmowy start

Pierwsze 20 odpowiedzi są dostępne od razu

Przeglądaj pełną listę 55 pytań. Pełne odpowiedzi, przykłady kodu i materiały do nauki odblokujesz w panelu.

Odblokuj 35 odpowiedzi

Podstawy Redis

Czym jest Redis i jakie są jego główne zastosowania?

Odpowiedź w 30 sekund: Redis (REmote DIctionary Server) to wysokowydajna, w pełni działająca w pamięci baza danych typu klucz-wartość, używana jako cache, broker wiadomości, kolejka zadań i magazyn sesji. Obsługuje bogaty zestaw struktur danych (stringi, listy, hashe, zbiory, sorted sety, streamy) oraz oferuje opcjonalną trwałość na dysku.

Odpowiedź w 2 minuty: Redis to open-source'owa baza danych typu key-value, która przechowuje całość danych w pamięci RAM, dzięki czemu osiąga ekstremalnie niskie opóźnienia (poniżej milisekundy) i przepustowość rzędu setek tysięcy operacji na sekundę z jednego węzła. W przeciwieństwie do prostych cache'y Redis nie jest tylko mapą stringów — udostępnia kilkanaście wyspecjalizowanych typów danych z atomowymi operacjami na nich.

Główne zastosowania to: cache aplikacyjny (przyspieszanie odczytów z baz relacyjnych), przechowywanie sesji użytkowników (np. w aplikacjach Node.js, Spring), kolejki zadań i pub/sub (Sidekiq, Bull, Celery używają Redisa pod spodem), rate limiting (atomowe INCR + EXPIRE), rankingi i leaderboardy (sorted sets), geolokalizacja (typ Geo), streamy zdarzeń (Redis Streams, alternatywa dla lekkiego Kafki) oraz wyszukiwanie pełnotekstowe i wektorowe (moduły RediSearch i Redis Stack).

Redis może działać jako single node, w trybie replikacji master-replica, w trybie Sentinel (wysoka dostępność) albo jako Redis Cluster (sharding pomiędzy wieloma węzłami). Dane można utrwalać na dysku przez snapshoty RDB i/lub append-only log AOF, co daje kompromis między czystym cache a pełnoprawną bazą danych.

Przykład kodu:

# Prosty cache klucz-wartość z czasem życia 60 sekund
redis-cli SET user:1001 "Anna Kowalska" EX 60
redis-cli GET user:1001
# "Anna Kowalska"

# Licznik atomowy - idealny do rate limitingu
redis-cli INCR api:calls:user:1001
redis-cli EXPIRE api:calls:user:1001 3600

# Lista zadań (kolejka FIFO)
redis-cli LPUSH zadania "wyslij-email:1001"
redis-cli RPOP zadania

# Ranking graczy (sorted set)
redis-cli ZADD ranking 1500 "gracz1" 2300 "gracz2"
redis-cli ZREVRANGE ranking 0 9 WITHSCORES

Diagram:

flowchart TD
    A[Aplikacja] --> B{Redis - in-memory}
    B --> C[Cache zapytan]
    B --> D[Sesje uzytkownikow]
    B --> E[Kolejki zadan]
    B --> F[Pub/Sub i Streams]
    B --> G[Rate limiting]
    B --> H[Rankingi i geo]
    B -.snapshot.-> I[(Dysk - RDB/AOF)]

Materiały

Dlaczego Redis jest tak szybki w porównaniu z bazami relacyjnymi?

Odpowiedź w 30 sekund: Redis trzyma wszystkie dane w pamięci RAM, używa prostego protokołu binarnego RESP, single-threadowej pętli zdarzeń z IO multiplexingiem oraz wysoko zoptymalizowanych struktur danych w C. Brak dyskowych odczytów, brak parsera SQL, brak złączeń i transakcji ACID — to wszystko daje opóźnienia rzędu mikrosekund.

Odpowiedź w 2 minuty: Pierwszy powód to lokalizacja danych — Redis trzyma wszystko w RAM, a dostęp do pamięci jest około 100 000 razy szybszy niż do losowego sektora na dysku HDD i kilkaset razy szybszy niż do SSD. Bazy relacyjne, nawet jeśli mają duży bufor cache, muszą zarządzać stronami danych, fsynkować WAL na dysk i radzić sobie z cache miss'ami.

Drugi powód to prostota modelu danych. Operacje takie jak GET, SET, INCR to dosłownie wskaźnik w hashmapie i kilkanaście instrukcji procesora. Brak parsera SQL, planera zapytań, optymalizatora, joinów i kontroli więzów referencyjnych radykalnie skraca ścieżkę wykonania.

Trzeci powód to architektura I/O. Redis używa jednego wątku do obsługi komend, ale wraz z mechanizmem epoll/kqueue/io_uring (multiplexing) potrafi obsłużyć dziesiątki tysięcy połączeń jednocześnie. Brak kontekstowych przełączeń wątków, brak locków, brak konkurencji o cache linie CPU. Dodatkowo protokół RESP jest tekstowo-binarny i bardzo tani do sparsowania.

Czwarty powód to optymalizacje niskiego poziomu — Redis ma własne implementacje struktur (ziplist, listpack, quicklist, intset, SDS — Simple Dynamic String), które są kompaktowe pamięciowo i cache-friendly. Wreszcie, pipelining i MULTI/EXEC pozwalają wysłać wiele komend w jednym round-tripie, eliminując opóźnienie sieci.

Przykład kodu:

# Benchmark - typowo 100k-200k ops/sec na jednym rdzeniu
redis-benchmark -t set,get -n 100000 -q
# SET: 142857.14 requests per second
# GET: 158730.16 requests per second

# Pipelining - 10x szybsze niz pojedyncze komendy
redis-benchmark -t set -n 100000 -P 16 -q
# SET: 1428571.40 requests per second (16 komend w pipeline)

# Pomiar opoznienia
redis-cli --latency
# min: 0, max: 1, avg: 0.08 (ms)

Diagram:

flowchart LR
    A[Klient] -- RESP --> B[Single thread event loop]
    B -- epoll/kqueue --> C[IO multiplexing]
    C --> D[Hashmapa w RAM]
    D --> E[Odpowiedz w mikrosekundach]
    F[Baza SQL] -.parser SQL.-> G[Planer]
    G -.join/index.-> H[Bufor + dysk]
    H -.ms-dziesiatki ms.-> I[Odpowiedz]

Materiały

Jaka jest różnica między Redis a Memcached?

Odpowiedź w 30 sekund: Memcached to prosty, wielowątkowy cache klucz-wartość obsługujący wyłącznie stringi — szybki, ale „głupi". Redis to baza danych w pamięci z wieloma typami danych, trwałością, replikacją, pub/sub, skryptami Lua, transakcjami i clusteringiem. Memcached wybiera się dla czystego cache'owania, Redis dla wszystkiego ponad to.

Odpowiedź w 2 minuty: Obie technologie powstały jako szybkie, in-memory key-value store'y, ale ich filozofie się rozeszły. Memcached pozostał minimalistyczny — przechowuje wyłącznie pary string -> string/blob (do 1 MB domyślnie), nie ma trwałości na dysku, nie ma replikacji, nie ma transakcji. Za to jest wielowątkowy z natury i potrafi liniowo skalować się po rdzeniach na jednej maszynie.

Redis poszedł w stronę „in-memory data structure server". Obsługuje stringi, listy, hashe, zbiory, sorted sety, streamy, bitmapy, hyperloglog, geo, JSON (z modułem), wektory (z modułem). Ma persistencję (RDB + AOF), replikację master-replica, sharding (Cluster), Pub/Sub, skrypty Lua, transakcje MULTI/EXEC, mechanizmy expiry i wbudowane eviction policies (LRU, LFU, allkeys-random).

Wybierz Memcached, jeśli potrzebujesz tylko prostego, ulotnego cache'u dla obiektów aplikacyjnych, masz dużo rdzeni i nie zależy ci na żadnych dodatkowych funkcjach. Wybierz Redis, jeśli oprócz cache potrzebujesz kolejek, rate limitingu, rankingów, pub/sub, sesji z trwałością, replikacji albo bogatszych operacji atomowych.

W praktyce większość nowych projektów wybiera Redis — różnica wydajnościowa jest niewielka, a możliwości nieporównywalnie większe.

Tabela porównawcza:

Cecha Redis Memcached
Typy danych string, list, hash, set, zset, stream, geo, bitmap, hll, json, vector tylko string/blob
Trwałość RDB + AOF brak
Replikacja master-replica, Sentinel brak natywnie
Sharding Redis Cluster client-side hashing
Wątkowość single-thread (od 6.0 wątki I/O) multi-thread
Maks. rozmiar wartości 512 MB 1 MB (konfigurowalne)
Pub/Sub i Streams tak nie
Skrypty Lua tak nie
Transakcje MULTI/EXEC brak
TTL na klucz tak (sekundy + milisekundy) tak (sekundy)
Eviction policies 8 polityk (LRU, LFU, ...) LRU

Przykład kodu:

# Redis - bogate operacje atomowe
redis-cli HSET user:1001 imie "Anna" wiek 30 miasto "Warszawa"
redis-cli HINCRBY user:1001 wiek 1
redis-cli HGETALL user:1001

# Memcached - tylko proste set/get (przez telnet/CLI)
# set user:1001 0 60 23
# {"imie":"Anna","wiek":30}
# STORED
# get user:1001

# Pub/Sub w Redis - niemozliwe w Memcached
redis-cli SUBSCRIBE kanal:zamowienia &
redis-cli PUBLISH kanal:zamowienia "nowe-zamowienie-12345"

Diagram:

flowchart TD
    A[Klient] --> B{Wybor cache}
    B -->|prosty key-value| C[Memcached]
    B -->|bogate struktury + persistencja| D[Redis]
    C --> E[Multi-thread<br/>tylko stringi<br/>brak trwalosci]
    D --> F[Single-thread<br/>typy: list/hash/set/zset/stream<br/>RDB + AOF + replika]

Materiały

Czy Redis jest single-threaded i jak to wpływa na wydajność?

Odpowiedź w 30 sekund: Główna pętla wykonywania komend w Redis jest jednowątkowa, co eliminuje locki i context switche, ale dzięki IO multiplexingowi (epoll/kqueue) obsługuje tysiące połączeń jednocześnie. Od Redis 6.0 można włączyć dodatkowe wątki I/O do parsowania sieci, a od 7.x niektóre operacje (np. UNLINK) są asynchroniczne. Pojedyncze, długie komendy mogą jednak zablokować cały serwer.

Odpowiedź w 2 minuty: Tak — komendy są wykonywane sekwencyjnie w jednym wątku. To celowy wybór projektowy. Dzięki temu wszystkie operacje na strukturach danych są z natury atomowe (nie potrzeba locków), nie ma rywalizacji o pamięć między wątkami, nie ma cache-line bouncingu między rdzeniami, a kod jest dużo prostszy i bardziej niezawodny.

Jak to się skaluje? Redis używa IO multiplexingu (epoll na Linuxie, kqueue na BSD/macOS, IOCP na Windowsie). Jedna pętla zdarzeń pyta jądro: „które z 10 000 socketów mają coś do przeczytania?" i przetwarza tylko te. Dlatego jeden wątek obsługuje setki tysięcy operacji na sekundę i tysiące równoległych klientów.

Od Redis 6.0 wprowadzono opcjonalne threaded I/O — parsowanie i wysyłka odpowiedzi może być rozdystrybuowana na kilka wątków (io-threads 4), podczas gdy samo wykonywanie komend nadal jest jednowątkowe. To podwaja przepustowość na maszynach z wieloma rdzeniami.

Pułapki: skoro jest tylko jeden wątek wykonawczy, długo działające komendy blokują wszystko. KEYS * na bazie z milionem kluczy, SMEMBERS na zbiorze z 500 tys. elementów, ciężki skrypt Lua, DEBUG SLEEP — wszystkie inne komendy czekają. Dlatego w produkcji używa się SCAN zamiast KEYS, SSCAN/HSCAN/ZSCAN zamiast operacji na całych kolekcjach, UNLINK zamiast DEL dla dużych kluczy (asynchroniczne zwalnianie pamięci) i monitoruje się slowlog.

Przykład kodu:

# ZLE - blokuje serwer na duzych bazach
redis-cli KEYS "user:*"

# DOBRZE - iteracyjnie, nieblokujaco
redis-cli SCAN 0 MATCH "user:*" COUNT 100

# UNLINK zamiast DEL dla duzych kluczy
redis-cli UNLINK ogromny-zbior

# Wlaczenie wielowatkowego I/O (redis.conf)
# io-threads 4
# io-threads-do-reads yes

# Diagnostyka wolnych komend
redis-cli CONFIG SET slowlog-log-slower-than 10000
redis-cli SLOWLOG GET 10

Diagram:

flowchart TD
    A[Klient 1] --> M[Socket 1]
    B[Klient 2] --> N[Socket 2]
    C[Klient N] --> O[Socket N]
    M --> P[epoll/kqueue<br/>IO multiplexing]
    N --> P
    O --> P
    P --> Q[Event loop<br/>jeden watek]
    Q --> R[Wykonanie komendy<br/>na strukturze w RAM]
    R --> S[Odpowiedz do klienta]
    T[io-threads 4<br/>od Redis 6.0] -.parsowanie/wysylka.-> P

Materiały

Czym różni się Redis od innych baz NoSQL (MongoDB, Cassandra)?

Odpowiedź w 30 sekund: Redis to in-memory key-value store nastawiony na ekstremalnie niskie opóźnienia i bogate struktury danych. MongoDB to dyskowa baza dokumentowa z zapytaniami ad-hoc, indeksami i agregacjami. Cassandra to rozproszona, masowo skalowalna baza kolumnowa (wide-column) optymalizowana pod ogromne zapisy i wysoką dostępność w wielu centrach danych.

Odpowiedź w 2 minuty: Każda z tych baz reprezentuje inną kategorię NoSQL i rozwiązuje inny problem.

Redis — key-value, w pełni in-memory, single-master (w klastrze sharding po slotach), priorytet to opóźnienie poniżej milisekundy i bogate operacje atomowe na strukturach (list, set, sorted set, stream). Świetny do cache, kolejek, sesji, rate limitingu, rankingów i pub/sub. Nie nadaje się jako jedyne źródło prawdy dla dużych zbiorów danych (RAM jest drogi, choć Redis on Flash i tiering to łagodzi).

MongoDB — dokumentowa baza danych, dane to dokumenty BSON (rozszerzony JSON) w kolekcjach. Wspiera bogate zapytania ad-hoc, indeksy (w tym wielokluczowe, geo, tekstowe), pipeline'y agregacyjne, transakcje multi-document (od 4.0) i replica sets z automatycznym failoverem. Wybierana jako podstawowa baza dla aplikacji o ewoluującym schemacie i potrzebie elastycznych zapytań.

Cassandra — wide-column, zaprojektowana pod ekstremalnie wysoką dostępność i skalowanie liniowe poprzez dodawanie węzłów. Architektura masterless (każdy węzeł jest równy), replikacja multi-region, model danych zoptymalizowany pod konkretne zapytania (modelowanie „query first"). Zapisy są szybsze niż odczyty (LSM-tree, commit log + memtable + SSTable). Idealna dla danych szeregów czasowych, telemetrii, IoT, logów — gdy zapis dominuje i potrzebujesz petabajtów.

W praktyce te bazy często współistnieją: Redis jako cache i kolejki, MongoDB jako główny store dokumentów aplikacyjnych, Cassandra jako warstwa analityczna/eventowa.

Tabela porównawcza:

Cecha Redis MongoDB Cassandra
Model danych key-value + struktury dokumenty BSON/JSON wide-column
Storage RAM (+ opcjonalny dysk) dysk (WiredTiger) dysk (LSM-tree)
Język zapytań własne komendy, Lua MQL, agregacje CQL (podobne do SQL)
Schemat brak elastyczny zdefiniowany
Skalowanie Redis Cluster (sharding) sharded cluster masterless, liniowe
Spójność strong (single-node) configurable (majority default) tunable (ONE/QUORUM/ALL)
Replikacja master-replica + Sentinel replica set multi-master, multi-DC
CAP CP (w klastrze) CP AP
Transakcje MULTI/EXEC, brak ACID multi-document ACID (4.0+) lekkie LWT
Typowe użycie cache, sesje, kolejki, rankingi aplikacje CRUD, katalogi, treści IoT, time-series, logi, eventy
Latencja odczytu mikrosekundy milisekundy milisekundy-dziesiątki ms

Przykład kodu:

# REDIS - klucz i struktura
redis-cli SET user:1001 '{"imie":"Anna","wiek":30}'
redis-cli ZADD ranking 1500 "anna"
redis-cli LPUSH kolejka:email "user:1001"

# MONGODB - dokument i zapytanie (mongosh)
# db.uzytkownicy.insertOne({_id: 1001, imie: "Anna", wiek: 30, tagi: ["premium"]})
# db.uzytkownicy.find({wiek: {$gte: 18}, tagi: "premium"})
# db.uzytkownicy.aggregate([{$group: {_id: "$miasto", liczba: {$sum: 1}}}])

# CASSANDRA - CQL, partycja + clustering key
# CREATE TABLE pomiary (
#   urzadzenie_id uuid,
#   czas timestamp,
#   wartosc double,
#   PRIMARY KEY (urzadzenie_id, czas)
# ) WITH CLUSTERING ORDER BY (czas DESC);
# SELECT * FROM pomiary WHERE urzadzenie_id = ? AND czas > ? LIMIT 100;

Diagram:

flowchart TD
    A[Wymagania] --> B{Co priorytet?}
    B -->|niska latencja + cache + kolejki| C[Redis<br/>key-value in-memory]
    B -->|elastyczne dokumenty + zapytania ad-hoc| D[MongoDB<br/>document store]
    B -->|ogromne zapisy + multi-DC + HA| E[Cassandra<br/>wide-column]
    C --> F[Cache, sesje, rankingi, pub/sub]
    D --> G[Aplikacje CRUD, CMS, katalogi]
    E --> H[IoT, time-series, logi, eventy]

Materiały

Typy danych

Jakie są podstawowe typy danych w Redis (String, List, Hash, Set, Sorted Set)?

Odpowiedź w 30 sekund: Redis oferuje pięć podstawowych typów danych: String (binarnie bezpieczne ciągi do 512 MB), List (uporządkowana lista, działa jak deque), Hash (mapa pól i wartości w jednym kluczu), Set (zbiór unikalnych elementów) oraz Sorted Set / ZSET (zbiór z wynikiem score, automatycznie sortowany). Każdy typ ma własny zestaw komend zoptymalizowanych pod konkretne wzorce użycia.

Odpowiedź w 2 minuty: String to najprostszy typ, przechowujący binarnie bezpieczny tekst, liczbę lub nawet zserializowany JSON. Obsługuje atomowe operacje INCR/DECR, dzięki czemu świetnie nadaje się na liczniki, flagi i cache. Limit pojedynczego stringa to 512 MB.

List to dwukierunkowa lista (quicklist) z O(1) na końcach, używana jako kolejka FIFO, stos LIFO lub strumień zdarzeń (LPUSH + BRPOP). Hash to mapa pól w obrębie jednego klucza – idealna do modelowania obiektów (np. profil użytkownika z polami name, email, age) bez tworzenia wielu osobnych kluczy.

Set to zbiór unikalnych elementów z operacjami algebraicznymi (SINTER, SUNION, SDIFF) – świetny do tagów, znajomych, unikalnych odwiedzin. Sorted Set (ZSET) dokłada do Set wartość liczbową score, która determinuje porządek – używany do rankingów, leaderboardów, kolejek priorytetowych i indeksowania czasu.

Oprócz tych pięciu Redis posiada też typy specjalistyczne: Streams, HyperLogLog, Bitmap, Bitfield i Geospatial, ale to właśnie tych pięć stanowi fundament większości aplikacji.

Przykład kodu:

# String – cache JSON-a użytkownika, O(1)
SET user:42 '{"name":"Anna","plan":"pro"}' EX 3600
INCR pageviews:home  # atomowy licznik

# List – kolejka zadań, LPUSH/RPOP O(1)
LPUSH jobs "send-email:42"
RPOP jobs

# Hash – obiekt w jednym kluczu, HSET O(1)
HSET user:42 name "Anna" email "anna@example.com" age 30
HGET user:42 email

# Set – unikalne tagi, SADD/SISMEMBER O(1)
SADD article:101:tags "redis" "nosql" "cache"
SINTER user:42:tags article:101:tags

# Sorted Set – ranking graczy, ZADD O(log N)
ZADD leaderboard 1500 "anna" 1820 "marek"
ZREVRANGE leaderboard 0 9 WITHSCORES  # TOP 10

Porównanie typów:

flowchart TB
    R[Redis – podstawowe typy danych]
    R --> S[String<br/>do 512 MB<br/>SET/GET/INCR O 1]
    R --> L[List<br/>quicklist dwukierunkowa<br/>LPUSH/RPOP O 1<br/>LINDEX O N]
    R --> H[Hash<br/>mapa pól-wartości<br/>HSET/HGET O 1<br/>HGETALL O N]
    R --> SE[Set<br/>unikalne elementy<br/>SADD/SISMEMBER O 1<br/>SINTER O N*M]
    R --> Z[Sorted Set ZSET<br/>skiplist + hashmap<br/>ZADD O log N<br/>ZRANGE O log N + M]

    S --> SU[Zastosowanie:<br/>cache, liczniki, sesje, flagi]
    L --> LU[Zastosowanie:<br/>kolejki FIFO, stosy, feed]
    H --> HU[Zastosowanie:<br/>obiekty, profile, konfiguracje]
    SE --> SEU[Zastosowanie:<br/>tagi, znajomi, unikalne wizyty]
    Z --> ZU[Zastosowanie:<br/>rankingi, kolejki priorytetowe, czas]

Materiały

Jak działa typ String i jakie są jego limity?

Odpowiedź w 30 sekund: String to binarnie bezpieczny ciąg bajtów – może przechowywać tekst, liczbę, JSON, a nawet obrazek czy plik. Maksymalny rozmiar to 512 MB na klucz. Większość operacji (SET, GET, INCR, APPEND) działa w O(1), a Redis traktuje liczby przechowywane jako string atomowo, dzięki INCR/DECR/INCRBYFLOAT.

Odpowiedź w 2 minuty: "Binarnie bezpieczny" oznacza, że Redis nie interpretuje zawartości – możesz tam wrzucić cokolwiek, nawet bajty zerowe. To czyni String uniwersalnym kontenerem na cache HTTP-response'ów, zserializowane obiekty (JSON, MessagePack, protobuf) lub krótkie pliki binarne.

Kluczową cechą jest atomowość operacji liczbowych: jeśli wartość da się zinterpretować jako 64-bitową liczbę całkowitą, możesz używać INCR, DECR, INCRBY bez ryzyka wyścigów – to jeden z najczęstszych wzorców do liczników, rate limiterów i sekwencji ID. Dla zmiennoprzecinkowych jest INCRBYFLOAT.

Redis pozwala też na ekspirację (EXPIRE, SET ... EX), warunkowe zapisy (SET ... NX – tylko jeśli nie istnieje, XX – tylko jeśli istnieje) oraz operacje na bitach (SETBIT, GETBIT, BITCOUNT) i podciągach (GETRANGE, SETRANGE).

Limity i pułapki: 512 MB to twardy limit pojedynczego klucza, ale w praktyce wartości powyżej kilkuset KB potrafią blokować event loop podczas serializacji. Dla dużych obiektów warto rozważyć Hash lub kompresję. Pamiętaj też, że KEYS * jest O(N) – do iteracji używaj SCAN.

Przykład kodu:

# Podstawowe SET/GET, O(1)
SET session:abc123 "user_id=42" EX 1800
GET session:abc123

# Atomowy licznik – idealne dla rate-limitera
INCR api:calls:user:42        # O(1), zwraca nową wartość
EXPIRE api:calls:user:42 60   # okno 60 s

# Warunkowy zapis – distributed lock
SET lock:order:9001 "worker-3" NX EX 10  # NX = tylko jeśli nie istnieje

# Operacje na liczbach zmiennoprzecinkowych
SET wallet:42 "100.50"
INCRBYFLOAT wallet:42 25.25   # -> 125.75

# Append i length – O(1)
APPEND log:today "linia nr 1\n"
STRLEN log:today

# Podciąg – O(N), N = długość zwracanego fragmentu
GETRANGE log:today 0 19

Materiały

Czym różni się List od Set w Redis i kiedy używać każdego z nich?

Odpowiedź w 30 sekund: List zachowuje kolejność i pozwala na duplikaty, działa jak dwukierunkowa kolejka (LPUSH/RPUSH/LPOP/RPOP w O(1)). Set przechowuje unikalne elementy bez kolejności, ale daje O(1) na sprawdzenie przynależności (SISMEMBER) i operacje algebraiczne (suma, część wspólna, różnica). Listy używamy do kolejek i historii, Setów do tagów, członkostwa i deduplikacji.

Odpowiedź w 2 minuty: List jest zaimplementowana jako quicklist (lista linkowanych ziplistów) – dodawanie i usuwanie z końców jest O(1), a dostęp po indeksie LINDEX to O(N). Dlatego List świetnie sprawdza się jako kolejka zadań (LPUSH + BRPOP – blokujące pobieranie), stos, ostatnie N elementów (LPUSH + LTRIM) czy feed aktywności. Element może powtarzać się wielokrotnie.

Set wewnętrznie to hashtable (lub listpack dla małych zbiorów). Każdy element jest unikalny, a sprawdzenie SISMEMBER to O(1) – niezastąpione gdy często pytasz "czy X należy do zbioru Y?" (np. "czy ten user widział ten artykuł?"). Set wspiera operacje teoriomnogościowe: SINTER (część wspólna), SUNION (suma), SDIFF (różnica), SRANDMEMBER (losowy element) – idealne do rekomendacji, znajomych, common-tags.

Kiedy co wybrać:

  • List, gdy: liczy się kolejność, dopuszczasz duplikaty, masz kolejkę FIFO/LIFO lub historię zdarzeń.
  • Set, gdy: zależy ci na unikalności, na szybkim teście przynależności, na operacjach typu "intersect" (wspólne tagi, wspólni znajomi).

Jeśli potrzebujesz jednego i drugiego (kolejność + unikalność), sięgnij po Sorted Set z score = timestamp.

Przykład kodu:

# LIST – kolejka zadań FIFO, O(1) na końcach
LPUSH jobs "task:send-email:42"
LPUSH jobs "task:send-email:43"
RPOP jobs              # -> "task:send-email:42" (najstarsze)
BRPOP jobs 5           # blokujące pobranie, max 5 s
LRANGE jobs 0 -1       # podgląd, O(N)
LTRIM feed:user:42 0 99  # zachowaj tylko ostatnie 100, O(N)

# SET – tagi artykułu, unikalne, O(1) na SADD/SISMEMBER
SADD article:101:tags "redis" "nosql" "cache"
SADD article:101:tags "redis"      # ignorowane, duplikat
SISMEMBER article:101:tags "redis" # -> 1, O(1)
SCARD article:101:tags             # liczność, O(1)

# Operacje algebraiczne – znajdź wspólne tagi dwóch artykułów
SADD article:102:tags "redis" "memcached" "cache"
SINTER article:101:tags article:102:tags   # -> {"redis","cache"}
SDIFF  article:101:tags article:102:tags   # -> {"nosql"}

# Losowy element – np. losowy artykuł rekomendowany
SRANDMEMBER articles:published 3

Materiały

Jakie są typowe zastosowania Sorted Set (ZSET) i jak działa scoring?

Odpowiedź w 30 sekund: Sorted Set to zbiór unikalnych elementów, w którym każdy element ma przypisany liczbowy score (double 64-bit). Redis utrzymuje wewnętrznie skiplist + hashtable, dzięki czemu dodawanie (ZADD) i odczyt po randze lub przedziale score'ów (ZRANGE, ZRANGEBYSCORE) działają w O(log N). Klasyczne zastosowania: leaderboardy, kolejki priorytetowe, indeksy czasowe i rate limiting w oknie przesuwnym.

Odpowiedź w 2 minuty: ZSET łączy zalety Setu (unikalność elementów) z porządkiem określonym przez score. Score to 64-bitowa liczba zmiennoprzecinkowa – możesz tam wrzucić cokolwiek liczbowo porównywalnego: punkty gracza, timestamp, priorytet, cenę, dystans. Elementy o równych score'ach są sortowane leksykograficznie.

Wewnętrzna struktura (skiplist + hash) daje O(log N) na większość operacji i O(log N + M) na zakresy (gdzie M to liczba zwróconych elementów). To dlatego ZSET jest narzędziem pierwszego wyboru wszędzie tam, gdzie potrzebujesz uporządkowanego widoku zbioru, który można szybko aktualizować.

Najczęstsze zastosowania:

  1. Leaderboard / ranking – ZADD leaderboard 1500 "anna", ZREVRANGE leaderboard 0 9 WITHSCORES zwraca TOP 10.
  2. Kolejka priorytetowa – score = priorytet, ZPOPMIN pobiera najpilniejsze.
  3. Indeks po czasie – score = unix timestamp; ZRANGEBYSCORE events 1700000000 1700003600 zwraca zdarzenia z danej godziny.
  4. Rate limiting (sliding window) – ZADD, potem ZREMRANGEBYSCORE usuwa wpisy starsze niż okno, a ZCARD mówi ile zostało.
  5. Auto-complete / sugestie – wszystkie elementy ze score 0, użycie ZRANGEBYLEX do prefix search.
  6. Geo wcześniej – Geospatial wewnętrznie jest ZSET-em z geohash jako score.

Przykład kodu:

# Leaderboard graczy, ZADD O(log N)
ZADD leaderboard 1500 "anna" 1820 "marek" 1200 "ola"
ZINCRBY leaderboard 50 "anna"      # +50 punktów, O(log N)
ZREVRANGE leaderboard 0 2 WITHSCORES   # TOP 3, O(log N + M)
ZRANK leaderboard "anna"               # pozycja od najniższego
ZREVRANK leaderboard "anna"            # pozycja od najwyższego

# Kolejka priorytetowa – mniejszy score = wyższy priorytet
ZADD jobs:queue 1 "critical:db-backup" 5 "normal:send-newsletter"
ZPOPMIN jobs:queue   # pobiera najpilniejsze, O(log N)

# Indeks czasowy – zdarzenia z ostatniej godziny
ZADD events 1700003600 "login:42" 1700003700 "purchase:42"
ZRANGEBYSCORE events 1700000000 1700003600 LIMIT 0 100

# Rate limit sliding window 60 s
ZADD ratelimit:user:42 1700003700 "req-uuid-1"
ZREMRANGEBYSCORE ratelimit:user:42 -inf 1700003640
ZCARD ratelimit:user:42   # ile zapytań w oknie

Jak score determinuje pozycję:

flowchart LR
    A["ZADD leaderboard<br/>score gracz"] --> B[Skiplist + Hashtable]
    B --> C{Sortowanie<br/>po score rosnąco}
    C --> D["Pozycja 1<br/>ola: 1200"]
    C --> E["Pozycja 2<br/>anna: 1500"]
    C --> F["Pozycja 3<br/>marek: 1820"]

    D --> G["ZRANGE 0 -1<br/>od najniższego score"]
    F --> H["ZREVRANGE 0 -1<br/>od najwyższego score = TOP"]

    G --> I["Wynik:<br/>ola, anna, marek"]
    H --> J["Wynik:<br/>marek, anna, ola"]

    K["ZINCRBY +200 ola"] --> L["ola: 1400<br/>nadal pozycja 1"]
    M["ZINCRBY +500 ola"] --> N["ola: 1700<br/>awans na pozycję 2"]

Materiały

Czym jest typ Hash i kiedy warto go używać zamiast wielu kluczy String?

Odpowiedź w 30 sekund: Hash to mapa pól (field) i wartości w obrębie jednego klucza Redis – odpowiednik obiektu/rekordu. Pozwala atomowo czytać i pisać poszczególne pola (HSET, HGET, HINCRBY, wszystkie O(1)), zamiast trzymać kilkanaście osobnych kluczy user:42:name, user:42:email. Oszczędza pamięć (małe Hashe są przechowywane jako listpack), ułatwia ekspirację całego obiektu i upraszcza zarządzanie.

Odpowiedź w 2 minuty: Hash modeluje obiekt: jeden klucz, dowolnie wiele pól. Klasyczny przykład – profil użytkownika z polami name, email, age, plan. Zamiast pięciu kluczy String używasz jednego user:42 z pięcioma polami. Operacje są atomowe per pole: HINCRBY user:42 login_count 1 zwiększy licznik bez kolizji z innym klientem aktualizującym email.

Zalety nad wieloma Stringami:

  1. Pamięć – małe Hashe (do hash-max-listpack-entries, domyślnie 128 pól i 64 bajty na wartość) są pakowane w listpack, co potrafi zmniejszyć zużycie RAM nawet 5-10×.
  2. Ekspirycja całości – jeden EXPIRE user:42 3600 wygasza cały obiekt; przy wielu Stringach musisz EXPIRE'ować każdy z osobna (Redis 7.4+ wprowadził HEXPIRE per pole).
  3. Bulk read/write – HMGET user:42 name email age zwraca trzy pola jednym round-tripem; HGETALL zwraca wszystko.
  4. Czytelność – jeden namespace, łatwiejsze do debugowania (HKEYS user:42).
  5. Atomowość per pole – HINCRBY, HSETNX działają jak INCR/SETNX ale w obrębie pola.

Kiedy NIE używać Hasha:

  • Gdy potrzebujesz ekspiracji per pole (do 7.4 niemożliwe natywnie).
  • Gdy wartość jednego pola jest duża (> 1 MB) – wtedy lepiej osobny String.
  • Gdy operujesz głównie na całych obiektach JSON – wówczas String + RedisJSON może być prostszy.
  • Gdy chcesz indeksować pojedyncze pola po stronie Redisa – do tego lepszy Sorted Set lub RediSearch.

Przykład kodu:

# Tworzenie profilu użytkownika, HSET O(1) na pole
HSET user:42 name "Anna" email "anna@example.com" age 30 plan "pro"

# Odczyt pojedynczego pola, O(1)
HGET user:42 email                  # -> "anna@example.com"

# Bulk read, O(N) gdzie N = liczba pól
HMGET user:42 name email plan
HGETALL user:42                     # wszystko, O(N)

# Atomowy licznik w obrębie obiektu
HINCRBY user:42 login_count 1       # O(1)
HINCRBYFLOAT user:42 balance -19.99 # O(1)

# Sprawdzenie/usunięcie pola
HEXISTS user:42 email               # -> 1
HDEL user:42 plan                   # usuwa pole
HKEYS user:42                       # lista pól
HLEN user:42                        # liczba pól, O(1)

# Ekspirycja całego obiektu (Redis < 7.4)
EXPIRE user:42 3600

# Ekspirycja per pole (Redis 7.4+)
HEXPIRE user:42 60 FIELDS 1 verification_code

Materiały

Czym są Streams w Redis i jak różnią się od Pub/Sub?

Odpowiedź w 30 sekund: Stream to append-only log zdarzeń z trwałą historią i consumer groups – każde zdarzenie ma unikalny ID timestamp-seq, można je czytać wielokrotnie, od dowolnego punktu w przeszłości, a konsumenci dostają wiadomości z potwierdzeniem (ACK). Pub/Sub to fire-and-forget broadcasting bez historii – jeśli subscriber jest offline, traci wiadomości. Streams = Kafka-lite w Redis, Pub/Sub = lekki broadcast w czasie rzeczywistym.

Odpowiedź w 2 minuty: Pub/Sub (PUBLISH/SUBSCRIBE) to klasyczny wzorzec wydawca-subskrybent. Redis wysyła wiadomość do wszystkich aktywnych subskrybentów kanału. Plusy: bardzo niska latencja, prostota. Minusy: brak persystencji (offline subscriber nic nie dostanie), brak potwierdzeń, brak filtrowania po offsetcie, brak współdzielenia obciążenia między wielu konsumentów.

Streams (dodane w Redis 5.0, XADD/XREAD/XREADGROUP) to trwały log dopisujący wpisy z auto-generowanym ID typu 1700003700123-0. Strumień pamięta historię – możesz czytać od początku (0), od końca ($), od konkretnego ID lub w blokujący sposób (BLOCK 0). Consumer groups pozwalają wielu konsumentom dzielić ładunek: każda wiadomość trafia do jednego konsumenta z grupy, a Redis śledzi co zostało potwierdzone (XACK) i co czeka w Pending Entries List (PEL) – dzięki temu po awarii konsumenta można zauważyć i przetworzyć nieodebrane wiadomości (XCLAIM, XAUTOCLAIM).

Kluczowe różnice:

Cecha Pub/Sub Streams
Persystencja Brak Tak (RDB/AOF)
Replay historii Nie Tak (od dowolnego ID)
Consumer groups Nie Tak (XREADGROUP)
Potwierdzenia (ACK) Nie Tak (XACK + PEL)
Maks. rozmiar – XADD MAXLEN do trimowania
Złożoność XADD/PUBLISH O(log N) PUBLISH O(N+M) XADD O(1)
Zastosowanie live notyfikacje, chat event sourcing, kolejki, audit log

Streams są droższe pamięciowo i konceptualnie, ale są niezawodne i nadają się na backbone event-driven architektury. Pub/Sub jest świetny do efemerycznych powiadomień (online status, ticker, livechat) gdzie utrata wiadomości jest akceptowalna.

Przykład kodu:

# --- Pub/Sub ---
# Terminal A: subscriber
SUBSCRIBE notifications     # czeka na wiadomości
# Terminal B: publisher
PUBLISH notifications "user:42 logged in"  # O(N+M), N=subskrybenci

# --- Streams ---
# Producent dodaje zdarzenie, XADD O(1)
XADD orders * user_id 42 amount 99.99 status "new"
# -> 1700003700123-0 (auto-ID: ms-seq)

# Trim do ostatnich 10 000 zdarzeń (aprox)
XADD orders MAXLEN ~ 10000 * user_id 43 amount 50.00 status "new"

# Konsument bez grupy – czyta od konkretnego ID
XREAD COUNT 10 STREAMS orders 0
XREAD BLOCK 5000 STREAMS orders $   # blokuj 5s czekając na nowe

# Consumer group – wielu konsumentów dzieli obciążenie
XGROUP CREATE orders order-processors $ MKSTREAM
XREADGROUP GROUP order-processors worker-1 COUNT 5 BLOCK 0 STREAMS orders >
XACK orders order-processors 1700003700123-0    # potwierdź przetworzenie

# Sprawdzenie nieprzetworzonych (Pending Entries List)
XPENDING orders order-processors
XCLAIM orders order-processors worker-2 60000 1700003700123-0  # przejmij od zawieszonego

Streams – producent vs consumer group:

sequenceDiagram
    participant P as Producent
    participant S as Redis Stream "orders"
    participant CG as Consumer Group "order-processors"
    participant W1 as Worker-1
    participant W2 as Worker-2

    P->>S: XADD orders * user_id 42 amount 99.99
    Note over S: ID: 1700003700123-0
    P->>S: XADD orders * user_id 43 amount 50.00
    Note over S: ID: 1700003700456-0

    W1->>CG: XREADGROUP GROUP order-processors worker-1 COUNT 1
    CG-->>W1: 1700003700123-0 user_id=42
    Note over CG: PEL: {123-0 -> worker-1}

    W2->>CG: XREADGROUP GROUP order-processors worker-2 COUNT 1
    CG-->>W2: 1700003700456-0 user_id=43
    Note over CG: PEL: {123-0 -> w-1, 456-0 -> w-2}

    W1->>CG: XACK orders order-processors 1700003700123-0
    Note over CG: PEL: {456-0 -> w-2}

    Note over W2: Worker-2 pada (timeout)
    W1->>CG: XAUTOCLAIM po 60s
    CG-->>W1: 1700003700456-0 (przejęte)
    W1->>CG: XACK orders order-processors 1700003700456-0

Materiały

Czym są HyperLogLog, Bitmap i Geospatial w Redis?

Odpowiedź w 30 sekund: To trzy specjalistyczne struktury Redis. HyperLogLog to probabilistyczny licznik unikalnych elementów ze stałym zużyciem pamięci ~12 KB i błędem ~0.81%. Bitmap to ciąg bitów (technicznie String z SETBIT/GETBIT) – idealny do flag obecności typu "kto był online dziś". Geospatial to nakładka na Sorted Set, która koduje lokalizacje jako geohash – pozwala na zapytania "co jest w promieniu X km od punktu".

Odpowiedź w 2 minuty: HyperLogLog (PFADD/PFCOUNT) rozwiązuje klasyczny problem: ile unikalnych odwiedzin miała strona? Klasyczny Set zajmie GB pamięci dla 100 mln użytkowników, HLL – stałe 12 KB, ze średnim błędem 0.81%. PFADD to O(1), PFCOUNT to O(1) na jeden HLL i O(N) przy łączeniu kilku (PFMERGE). Stosujemy do unique visitors, unique searches, monitoringu kardynalności.

Bitmap to nie osobny typ – to String używany bitowo. SETBIT key offset 0|1, GETBIT key offset, BITCOUNT key (popcount), BITOP AND/OR/XOR/NOT. Klasyczne zastosowanie: aktywność użytkownika – klucz active:2025-05-28, gdzie bit numer X to "user X był aktywny". 1 mln użytkowników to ~125 KB. BITOP AND active:2025-05-27 active:2025-05-28 zwraca bitmapę userów aktywnych w obu dniach. Bitfield rozszerza to o operacje na N-bitowych liczbach całkowitych.

Geospatial (GEOADD/GEOSEARCH) wewnętrznie jest Sorted Setem, gdzie score to geohash kodujący długość i szerokość geograficzną. Dzięki temu sąsiednie lokalizacje mają zbliżony score i Redis może efektywnie filtrować je po zakresie. Dostępne komendy: GEOADD (dodanie punktu), GEOSEARCH (wyszukaj w promieniu lub prostokącie), GEODIST (odległość między punktami), GEOPOS (współrzędne). Złożoność GEOSEARCH to O(N + log M), świetnie nadaje się do "restauracje w promieniu 1 km", "dostępne taxi", "store locator".

Przykład kodu:

# --- HyperLogLog – unikalne odwiedziny strony ---
PFADD visitors:2025-05-28 "user:42" "user:43" "user:42"   # 42 liczone raz
PFCOUNT visitors:2025-05-28           # ~2, O(1)
PFMERGE visitors:week visitors:2025-05-27 visitors:2025-05-28
PFCOUNT visitors:week                 # unikalni za 2 dni

# --- Bitmap – kto był aktywny dziś ---
SETBIT active:2025-05-28 42 1         # user 42 -> aktywny, O(1)
SETBIT active:2025-05-28 43 1
GETBIT active:2025-05-28 42           # -> 1
BITCOUNT active:2025-05-28            # ilu userów aktywnych, O(N)

# Retencja: kto był aktywny we wszystkich 3 dniach?
BITOP AND active:both active:2025-05-26 active:2025-05-27 active:2025-05-28
BITCOUNT active:both

# Bitfield – 8-bitowy licznik per użytkownik
BITFIELD counters SET u8 #42 100 INCRBY u8 #42 5  # user 42 -> 105

# --- Geospatial – punkty na mapie ---
GEOADD restaurants -73.985 40.748 "Pizza-NYC" -73.990 40.750 "Sushi-NYC"
GEODIST restaurants "Pizza-NYC" "Sushi-NYC" km     # odległość
GEOSEARCH restaurants FROMLONLAT -73.987 40.749 BYRADIUS 1 km ASC
# -> lista restauracji w promieniu 1 km, posortowana od najbliższej, O(N+log M)
GEOSEARCH restaurants FROMMEMBER "Pizza-NYC" BYBOX 2 2 km ASC COUNT 10

Materiały

Persystencja danych

Jakie są mechanizmy persystencji w Redis (RDB, AOF)?

Odpowiedź w 30 sekund: Redis oferuje dwa główne mechanizmy persystencji: RDB (Redis Database) tworzy migawki (snapshoty) całej bazy w wyznaczonych momentach, a AOF (Append Only File) loguje każdą operację zapisu do pliku. Można ich używać niezależnie lub łącznie, aby uzyskać najlepszy kompromis między wydajnością a trwałością danych.

Odpowiedź w 2 minuty: RDB to mechanizm tworzenia migawek w punkcie czasu (point-in-time snapshot). Redis zapisuje w plik binarny dump.rdb cały stan bazy danych zgodnie z regułami save lub po wywołaniu komend SAVE/BGSAVE. Operacja BGSAVE używa wywołania systemowego fork(), dzięki czemu dziecko zapisuje migawkę bez blokowania głównego wątku obsługującego klientów. RDB daje kompaktowe, łatwe do skopiowania pliki i bardzo szybki restart, ale w razie awarii tracimy wszystkie zapisy od ostatniego snapshotu.

AOF działa zupełnie inaczej: każda komenda modyfikująca stan (np. SET, LPUSH, INCR) jest dopisywana do pliku appendonly.aof w formacie protokołu RESP. Plik jest okresowo synchronizowany na dysk poprzez fsync() z konfigurowalną częstotliwością (always, everysec, no). AOF zapewnia znacznie wyższą trwałość danych — typowo można stracić maksymalnie sekundę zapisów. Wadą jest większy rozmiar pliku oraz dłuższy czas restartu, ponieważ Redis musi odtworzyć wszystkie operacje. Mechanizm AOF rewrite okresowo kompaktuje plik, eliminując nadmiarowe komendy.

Od Redis 7.0 AOF używa nowego formatu multi-part (appendonly.aof.1.base.rdb + plik incremental), co łączy zalety RDB jako bazy z dopisywaniem AOF dla świeżych zmian. Domyślnie w najnowszych wersjach Redis preferuje persystencję hybrydową, łączącą oba mechanizmy.

Przykład kodu:

# redis.conf - podstawowa konfiguracja persystencji

# === RDB - migawki w punkcie czasu ===
# Zapis co 900s jeśli wystąpiła min. 1 zmiana
save 900 1
# Zapis co 300s jeśli wystąpiło min. 10 zmian
save 300 10
# Zapis co 60s jeśli wystąpiło min. 10 000 zmian
save 60 10000
# Nazwa pliku migawki
dbfilename dump.rdb
# Katalog na pliki persystencji
dir /var/lib/redis

# === AOF - log każdej operacji zapisu ===
appendonly yes
appendfilename "appendonly.aof"
# fsync co sekundę - rozsądny kompromis
appendfsync everysec

# Wyłącz zatrzymywanie zapisu gdy RDB nie powiedzie się
stop-writes-on-bgsave-error no

Materiały

Jaka jest różnica między RDB snapshotami a AOF (Append Only File)?

Odpowiedź w 30 sekund: RDB to binarna migawka całej bazy danych w jednym punkcie czasu — mała, szybka do wczytania, ale gubi zapisy między snapshotami. AOF to ciągły log wszystkich operacji modyfikujących — daje wyższą trwałość (typowo strata <1s), kosztem większego pliku, dłuższego restartu i nieco gorszej wydajności zapisu.

Odpowiedź w 2 minuty: RDB i AOF różnią się fundamentalnie filozofią. RDB rejestruje stan bazy „as is" w danej chwili — to jak zdjęcie. Plik jest binarny, mocno skompresowany i zwykle dziesiątki razy mniejszy od AOF dla tego samego zestawu danych. Restart polega po prostu na zmapowaniu struktur z pliku do pamięci, co jest błyskawiczne. Jednak między dwoma snapshotami wszystkie zapisy są nietrwałe — awaria zasilania może oznaczać utratę nawet kilkudziesięciu minut danych.

AOF zapisuje historię operacji — to jak nagranie z kamery. Każda komenda SET, DEL, LPUSH ląduje w pliku. Restart polega na replay'u tych komend w głównym wątku Redis, co przy dużych plikach AOF zajmuje znacznie więcej czasu niż wczytanie RDB. Z drugiej strony, przy appendfsync everysec ryzyko utraty danych jest sprowadzone do maks. 1 sekundy.

Diagramy pokazują kompromisy w obu rozwiązaniach:

graph TB
    subgraph "RDB Snapshot"
        R1[Migawka co N sekund/zmian] --> R2[Plik binarny dump.rdb]
        R2 --> R3[fork procesu w tle]
        R3 --> R4[Mały rozmiar pliku]
        R4 --> R5[Szybki restart]
        R5 --> R6[Ryzyko utraty zapisow<br/>od ostatniej migawki]
    end

    subgraph "AOF Log"
        A1[Kazda komenda zapisu] --> A2[Dopisanie do appendonly.aof]
        A2 --> A3[fsync wg polityki]
        A3 --> A4[Duzy rozmiar pliku]
        A4 --> A5[Wolniejszy restart - replay]
        A5 --> A6[Strata <1s przy everysec]
    end

    style R5 fill:#9f9
    style R6 fill:#f99
    style A6 fill:#9f9
    style A5 fill:#f99
Aspekt RDB AOF
Rozmiar pliku Mały (binarny, skompresowany) Duży (tekstowy log RESP)
Czas restartu Bardzo szybki (sekundy) Wolniejszy (replay komend)
fsync / trwałość Tylko przy snapshot always / everysec / no
Ryzyko utraty danych Wysokie (minuty) Niskie (do 1s przy everysec)
Wpływ na wydajność Niski (fork w tle) Wyższy (fsync na każdej operacji)
Złożoność konfiguracji Niska (save rules) Wyższa (rewrite, fsync policy)
Idealny scenariusz Backup, replikacja, dev Produkcja z wymogiem trwałości
Możliwość naprawy Trudna (binarne) Łatwiejsza (redis-check-aof --fix)

Przykład kodu:

# redis.conf - porównanie konfiguracji

# === Wariant tylko RDB (snapshot only) ===
save 900 1
save 300 10
save 60 10000
appendonly no
# Rezultat: maly plik, szybki restart, ryzyko utraty danych

# === Wariant tylko AOF (durability-first) ===
save ""                  # wylacz RDB
appendonly yes
appendfsync everysec     # rozsadny default
# Rezultat: duzy plik, wolniejszy restart, strata <1s

# === Wariant hybrydowy (zalecany) ===
save 3600 1
save 300 100
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes  # AOF zaczyna sie od RDB snapshot
# Rezultat: szybki restart + wysoka trwalosc

Materiały

Kiedy używać RDB, AOF, a kiedy obu jednocześnie?

Odpowiedź w 30 sekund: Sam RDB wybieramy do cache'u, dev/test oraz gdy dopuszczalna jest strata kilku minut danych. Sam AOF — gdy zależy nam głównie na trwałości, a możemy zaakceptować wolniejszy restart. Oba jednocześnie (zalecane na produkcji) — gdy chcemy zarówno szybki restart, jak i ochronę przed utratą danych.

Odpowiedź w 2 minuty: Wybór persystencji zależy od profilu obciążenia i wymagań biznesowych. Sam RDB sprawdza się świetnie w środowiskach, gdzie Redis pełni rolę cache'u — dane można odtworzyć z głównego źródła (np. PostgreSQL), więc straty są akceptowalne. RDB jest też idealny do snapshotów backupowych: jeden plik łatwo skopiować na S3 lub archiwizować.

Sam AOF wybierzemy w sytuacjach, gdy każda operacja musi przetrwać restart. Przykład: licznik transakcji, sesje użytkowników bez fallbacku do bazy, kolejki zadań typu Sidekiq. Strata sekundy danych przy everysec jest zwykle akceptowalna, a always daje gwarancję pełnej trwałości kosztem dramatycznego spadku throughput'u.

Oba mechanizmy łącznie to dziś rekomendowany przez Redis Labs standard produkcyjny. Przy restarcie Redis wczyta AOF, bo zawiera nowsze zapisy. RDB służy wtedy do szybkiego klonowania instancji, backupów oraz jako tzw. "RDB preamble" w AOF (dyrektywa aof-use-rdb-preamble yes) — AOF zaczyna się od skompresowanego RDB, a dopiero potem zawiera surowe komendy. Daje to szybki restart porównywalny z RDB oraz wysoką trwałość AOF.

flowchart TD
    Start[Jaki use case?] --> Cache{Cache lub<br/>dane re-buildowalne?}
    Cache -->|Tak| RDB[Tylko RDB<br/>save 900 1]
    Cache -->|Nie| Critical{Kazda operacja<br/>krytyczna?}
    Critical -->|Tak, max trwalosc| AOFAlways[AOF appendfsync always]
    Critical -->|Akceptujemy 1s straty| Both[RDB + AOF<br/>everysec + rdb-preamble]
    Critical -->|Tylko trwalosc| AOFOnly[Tylko AOF<br/>appendfsync everysec]

    style RDB fill:#fdb
    style AOFOnly fill:#bdf
    style Both fill:#bfb
    style AOFAlways fill:#fbb

Przykład kodu:

# redis.conf - rekomendowana hybrydowa konfiguracja produkcyjna

# === RDB jako szybki backup i preamble dla AOF ===
save 3600 1        # co godzine jesli min. 1 zmiana
save 300 100       # co 5 min jesli min. 100 zmian
save 60 10000      # co minute jesli min. 10k zmian
dbfilename dump.rdb
rdbcompression yes
rdbchecksum yes

# === AOF dla wysokiej trwalosci ===
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

# === Kluczowa opcja: hybrydowy format ===
# AOF zaczyna sie od binarnego snapshotu RDB,
# potem zawiera surowe komendy - szybki restart!
aof-use-rdb-preamble yes

# Auto-rewrite gdy AOF urosnie 2x od poprzedniego rewrite
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

Materiały

Jak skonfigurować częstotliwość zapisów RDB i fsync dla AOF?

Odpowiedź w 30 sekund: Dla RDB używamy dyrektyw save <sekundy> <zmiany> — Redis wykona migawkę, gdy oba warunki są spełnione. Dla AOF konfigurujemy appendfsync w trzech trybach: always (każda komenda), everysec (co sekundę, default i polecany) lub no (system operacyjny decyduje).

Odpowiedź w 2 minuty: Konfiguracja RDB opiera się na regułach save N M, gdzie N to odstęp w sekundach, a M to minimalna liczba zmienionych kluczy. Można zdefiniować wiele reguł — Redis wykona snapshot, gdy spełniona zostanie którakolwiek z nich. Aby całkowicie wyłączyć RDB, używamy save "". Dodatkowo stop-writes-on-bgsave-error yes (default) blokuje zapisy, gdy snapshot się nie powiedzie — to zabezpieczenie, ale w niektórych scenariuszach (cache) lepiej ustawić no.

Dla AOF kluczowa jest dyrektywa appendfsync:

  • always — fsync() po każdej komendzie. Najwyższa trwałość (zero data loss), ale drastycznie spada throughput, bo każdy zapis czeka na fizyczny zapis na dysk.
  • everysec — fsync() raz na sekundę w osobnym wątku. Default i sweet spot: maks. 1s straty przy znikomym wpływie na wydajność.
  • no — Redis nigdy sam nie wywołuje fsync(), polega na flushowaniu przez system operacyjny (zwykle co 30s na Linuksie). Najszybsze, ale duże ryzyko utraty danych.

Dodatkowo AOF korzysta z mechanizmu rewrite — okresowo plik jest kompaktowany w tle. Sterujemy tym dwoma parametrami: auto-aof-rewrite-percentage 100 (rewrite gdy plik urośnie 2x od ostatniego rewrite) oraz auto-aof-rewrite-min-size 64mb (nie rób rewrite dla małych plików).

Przykład kodu:

# redis.conf - szczegolowa konfiguracja persystencji

# === RDB: czestotliwosc snapshotow ===
# Format: save <sekundy> <minimalna liczba zmian>
save 900 1         # po 15 min jesli min. 1 klucz zmieniony
save 300 10        # po 5 min jesli min. 10 kluczy zmienione
save 60 10000      # po minucie jesli min. 10k zmian
# Aby calkowicie wylaczyc RDB:
# save ""

# Co zrobic gdy snapshot sie nie powiedzie
stop-writes-on-bgsave-error yes   # zablokuj zapisy (default)
rdbcompression yes                # kompresja LZF
rdbchecksum yes                   # CRC64 do wykrywania uszkodzen

# === AOF: polityka fsync ===
appendonly yes
appendfilename "appendonly.aof"

# Wybierz JEDNA z trzech opcji:
# appendfsync always       # max trwalosc, wolne
appendfsync everysec       # ZALECANE - balans
# appendfsync no           # max szybkosc, ryzyko utraty 30s+

# Nie blokuj fsync podczas BGSAVE/BGREWRITEAOF
no-appendfsync-on-rewrite no

# === AOF rewrite (kompaktowanie) ===
auto-aof-rewrite-percentage 100   # rewrite gdy plik 2x wiekszy
auto-aof-rewrite-min-size 64mb    # tylko dla plikow >= 64MB

# Ladowanie uszkodzonego AOF
aof-load-truncated yes            # zaladuj pomijajac uszkodzony koniec

Materiały

Co dzieje się z danymi gdy Redis się restartuje?

Odpowiedź w 30 sekund: Przy restarcie Redis ładuje dane do pamięci w określonej kolejności: najpierw sprawdza AOF (jeśli włączony), w przeciwnym razie ładuje RDB. Jeśli żaden plik nie istnieje, startuje z pustą bazą. Wszystko, co nie zostało zapisane przed crashem, jest tracone — stąd kluczowa rola odpowiedniej konfiguracji persystencji.

Odpowiedź w 2 minuty: Proces startu Redis przebiega według ścisłego algorytmu: jeśli w dir znajduje się plik AOF i appendonly yes, Redis odtworzy stan właśnie z niego — AOF jest uznawany za bardziej aktualny niż RDB. Jeśli AOF jest wyłączony lub plik nie istnieje, Redis załaduje dump.rdb. Gdy żadnego z plików nie ma, baza startuje pusta.

W trybie hybrydowym z aof-use-rdb-preamble yes plik AOF zaczyna się od binarnego dumpu RDB (szybkie wczytanie do pamięci), po czym Redis odtwarza ogon — listę komend wykonanych od ostatniego rewrite. To daje najlepsze z obu światów: szybki restart i pełną trwałość.

Co tracimy przy crashu? Zależy od konfiguracji:

  • Bez persystencji — wszystkie dane (Redis jako pure cache)
  • Tylko RDB — wszystko od ostatniego snapshotu (minuty do godzin)
  • AOF everysec — maks. 1 sekunda zapisów
  • AOF always — zero strat (ale dramatyczny narzut wydajnościowy)

Jeśli plik AOF jest uszkodzony (np. dysk się zapełnił w trakcie zapisu), aof-load-truncated yes pozwala załadować plik pomijając uszkodzony koniec. Dla mocniejszych przypadków używamy narzędzia redis-check-aof --fix appendonly.aof. Analogicznie dla RDB: redis-check-rdb dump.rdb.

flowchart TD
    Start([Redis sie uruchamia]) --> CheckAOF{appendonly = yes<br/>i plik AOF istnieje?}

    CheckAOF -->|Tak| AOFValid{Plik AOF<br/>nieuszkodzony?}
    AOFValid -->|Tak| LoadAOF[Wczytaj AOF<br/>do pamieci]
    AOFValid -->|Nie| CheckTruncated{aof-load-truncated<br/>= yes?}
    CheckTruncated -->|Tak| LoadPartial[Wczytaj AOF<br/>pomijajac uszkodzony koniec]
    CheckTruncated -->|Nie| FailStart[Redis NIE startuje<br/>- wymagana naprawa]

    CheckAOF -->|Nie| CheckRDB{Plik dump.rdb<br/>istnieje?}
    CheckRDB -->|Tak| LoadRDB[Wczytaj RDB<br/>snapshot do pamieci]
    CheckRDB -->|Nie| EmptyDB[Start z pusta baza]

    LoadAOF --> Ready([Redis gotowy<br/>do polaczen])
    LoadPartial --> Ready
    LoadRDB --> Ready
    EmptyDB --> Ready
    FailStart --> Fix[redis-check-aof --fix]
    Fix --> Start

    style LoadAOF fill:#bfb
    style LoadRDB fill:#bdf
    style EmptyDB fill:#fdb
    style FailStart fill:#f99
    style Ready fill:#9f9

Przykład kodu:

# redis.conf - bezpieczna konfiguracja na wypadek restartu

# === Priorytet: AOF przed RDB ===
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes

# === Toleruj uszkodzony koniec AOF ===
# Po crashu Redis zaladuje plik do ostatniej zdrowej komendy
aof-load-truncated yes

# === Backup RDB co godzine ===
save 3600 1
dir /var/lib/redis
dbfilename dump.rdb

# === Diagnostyka i naprawa (z linii polecen) ===
# Sprawdz integralnosc RDB:
#   redis-check-rdb /var/lib/redis/dump.rdb
# Napraw uszkodzony AOF:
#   redis-check-aof --fix /var/lib/redis/appendonly.aof
# Sprawdz logi po restarcie:
#   tail -f /var/log/redis/redis-server.log

Materiały

Replikacja i wysoka dostępność

Jak działa replikacja master-replica w Redis?

Odpowiedź w 30 sekund: Redis używa replikacji asynchronicznej, w której jeden węzeł master replikuje dane do jednej lub wielu replik. Master wysyła strumień komend do replik przez połączenie TCP, a repliki odtwarzają je, utrzymując kopię danych. Replikacja jest domyślnie eventually consistent, więc replika może chwilowo mieć starsze dane niż master.

Odpowiedź w 2 minuty: Replikacja w Redis działa w modelu leader-follower (master-replica). Master obsługuje zapisy i odczyty, a repliki domyślnie służą do odczytów oraz jako kopie zapasowe. Po połączeniu replika wykonuje pełną synchronizację (full resync), podczas której master zapisuje snapshot RDB i wysyła go do repliki razem z buforowanymi komendami zebranymi w trakcie tej operacji. Po pierwszej synchronizacji wchodzi w tryb replikacji przyrostowej.

Redis 2.8+ wspiera partial resynchronization: master utrzymuje cykliczny bufor (replication backlog) ostatnich komend i unikalny replication ID. Gdy replika rozłączy się na chwilę, może odzyskać tylko brakujące komendy bez pełnego resyncu, o ile bufor je jeszcze zawiera (parametr repl-backlog-size).

Replikacja jest asynchroniczna - master potwierdza klientowi zapis zanim repliki go odbiorą. To oznacza eventual consistency: w razie awarii mastera świeżo zapisane dane mogą zostać utracone, jeśli nie zdążyły dotrzeć do replik. Komenda WAIT numreplicas timeout pozwala wymusić synchroniczne potwierdzenie z określonej liczby replik, ale nie gwarantuje to pełnej spójności (nie jest to consensus).

Repliki mogą być również źródłem dla kolejnych replik (replikacja kaskadowa), co odciąża mastera przy dużej liczbie konsumentów.

Przykład kodu:

# Konfiguracja repliki w pliku redis.conf
replicaof 192.168.1.10 6379
# Repliki są domyślnie tylko do odczytu
replica-read-only yes
# Rozmiar bufora replikacji - im większy, tym dłuższe odłączenie jest tolerowane
repl-backlog-size 1mb

# Dynamiczne ustawienie repliki z CLI
redis-cli -h 192.168.1.20 -p 6379
> REPLICAOF 192.168.1.10 6379
> INFO replication

# Wymuszenie potwierdzenia zapisu z 2 replik (timeout 100ms)
> SET klucz wartosc
> WAIT 2 100

Diagram:

flowchart LR
    Klient[Klient zapisujący] -->|SET klucz| Master[(Master Redis)]
    Master -.->|replikacja async| Replika1[(Replika 1)]
    Master -.->|replikacja async| Replika2[(Replika 2)]
    Master -.->|replikacja async| Replika3[(Replika 3)]
    KlientR1[Klient odczytu] -->|GET klucz| Replika1
    KlientR2[Klient odczytu] -->|GET klucz| Replika2
    Replika3 -.->|kaskada| Replika4[(Replika 4)]

Materiały

Czym jest Redis Sentinel i jak zapewnia wysoką dostępność?

Odpowiedź w 30 sekund: Redis Sentinel to system monitorujący instancje Redis, który automatycznie wykrywa awarie mastera i przeprowadza failover, promując jedną z replik na nowego mastera. Sentinel działa jako rozproszony klaster procesów osiągających konsensus przez quorum, co zapobiega błędnym decyzjom typu split-brain.

Odpowiedź w 2 minuty: Sentinel rozwiązuje problem wysokiej dostępności w klasycznej topologii master-replica. Sam Redis nie wykonuje failoveru automatycznie - bez Sentinela administrator musiałby ręcznie promować replikę. Sentinel uruchamia się jako osobny proces (zwykle 3 lub 5 instancji rozłożonych na różnych maszynach) i ciągle pinguje monitorowane instancje.

Główne funkcje Sentinela: monitoring (sprawdzanie dostępności master i replik), powiadomienia (alerty o awariach), automatyczny failover (promocja repliki gdy master jest niedostępny) oraz service discovery (klient pyta Sentinela o aktualny adres mastera).

Failover wymaga konsensusu: gdy jeden Sentinel uzna mastera za nieosiągalnego, oznacza go jako Subjective Down (SDOWN). Gdy wystarczająca liczba Sentineli (quorum) potwierdzi awarię, master przechodzi w stan Objective Down (ODOWN). Wtedy Sentinele wybierają lidera (za pomocą algorytmu opartego o Raft), który przeprowadza failover: wybiera najlepszą replikę (najwyższy priority, najnowsze dane), promuje ją komendą REPLICAOF NO ONE, a pozostałe repliki rekonfiguruje do nowego mastera.

Quorum powinien być ustawiony na większość Sentineli (np. 2 z 3, 3 z 5), aby uniknąć split-brain. Klient łączący się z Redisem przez Sentinela odpytuje go o aktualny adres mastera (SENTINEL get-master-addr-by-name) i subskrybuje powiadomienia o zmianach.

Przykład kodu:

# Minimalna konfiguracja sentinel.conf
port 26379
# Monitoruj mastera o nazwie "mymaster", quorum=2 sentinele muszą uznać go za down
sentinel monitor mymaster 192.168.1.10 6379 2
# Po jakim czasie uznać instancję za nieosiągalną (ms)
sentinel down-after-milliseconds mymaster 5000
# Limit czasu na failover
sentinel failover-timeout mymaster 60000
# Hasło do autoryzacji (jeśli wymagane)
sentinel auth-pass mymaster sekretne-haslo

# Uruchomienie Sentinela
redis-sentinel /etc/redis/sentinel.conf

# Sprawdzenie stanu z poziomu klienta
redis-cli -p 26379 SENTINEL master mymaster
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster

Diagram:

flowchart TB
    subgraph SentinelCluster[Klaster Sentinel - quorum=2]
        S1[Sentinel 1]
        S2[Sentinel 2]
        S3[Sentinel 3]
    end
    subgraph RedisCluster[Instancje Redis]
        M[(Master)]
        R1[(Replika 1)]
        R2[(Replika 2)]
    end
    S1 -.->|monitoring PING| M
    S2 -.->|monitoring PING| M
    S3 -.->|monitoring PING| M
    S1 -.-> R1
    S2 -.-> R2
    S1 <-->|konsensus quorum| S2
    S2 <-->|konsensus quorum| S3
    Klient[Aplikacja] -->|"pytaj o aktualny master"| S1
    Klient -->|zapis/odczyt| M

Materiały

Jak działa Redis Cluster i jakie są jego ograniczenia?

Odpowiedź w 30 sekund: Redis Cluster to natywne rozwiązanie do skalowania horyzontalnego, które dzieli dane na 16384 slotów rozproszonych pomiędzy wiele węzłów master, każdy z własnymi replikami. Klaster oferuje automatyczny sharding, failover i komunikację bez proxy, ale wymusza ograniczenia takie jak brak operacji wielokluczowych między slotami i brak transakcji rozproszonych.

Odpowiedź w 2 minuty: Redis Cluster to wbudowany w Redis tryb rozproszony, który łączy partycjonowanie danych z wysoką dostępnością. Każdy klucz jest deterministycznie mapowany na jeden z 16384 slotów, a sloty są przydzielone do węzłów master. Minimalny działający klaster składa się z 3 masterów (każdy z 1 repliką, czyli 6 instancji łącznie).

Węzły komunikują się przez gossip protocol na osobnym porcie cluster bus (zwykle port klienta + 10000), wymieniając informacje o topologii, slotach i stanie zdrowia. Klient łączy się bezpośrednio z węzłami - gdy trafi na zły węzeł, otrzymuje przekierowanie MOVED (stałe przeniesienie slotu) lub ASK (chwilowe podczas migracji slotów). Inteligentni klienci (smart clients) cachują mapę slotów, więc kolejne zapytania trafiają od razu we właściwy węzeł.

Ograniczenia Redis Cluster:

  • Operacje wielokluczowe działają tylko gdy wszystkie klucze są w tym samym slocie - wymaga to użycia hash tagów {tag} w nazwach kluczy
  • Brak transakcji rozproszonych - MULTI/EXEC działa tylko w obrębie jednego węzła
  • Brak komendy SELECT - Cluster używa tylko bazy 0
  • Replikacja jest asynchroniczna, więc failover może powodować utratę ostatnich zapisów (eventual consistency)
  • Pub/Sub w wersji standardowej jest broadcastowany do wszystkich węzłów; w Redis 7+ dostępne sharded pub/sub
  • Minimum 3 masterów - mniej nie zapewnia bezpiecznego konsensusu
  • Skrypty Lua muszą operować na kluczach z jednego slotu

Przykład kodu:

# Utworzenie klastra z 6 węzłami (3 master + 3 replicas)
# Najpierw uruchom 6 instancji z cluster-enabled yes
redis-cli --cluster create \
  127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
  127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
  --cluster-replicas 1

# Konfiguracja w pliku redis.conf
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000

# Klient w trybie cluster (automatyczne podążanie za MOVED/ASK)
redis-cli -c -p 7000
> SET klucz1 wartosc
-> Redirected to slot [9189] located at 127.0.0.1:7001
OK

# Hash tag - wymusza wspólny slot dla powiązanych kluczy
> MSET {uzytkownik:42}:imie Jan {uzytkownik:42}:email jan@example.com

Diagram:

flowchart TB
    Klient[Klient Smart]
    subgraph Cluster[Redis Cluster - 16384 slotów]
        subgraph Shard1[Shard 1: sloty 0-5460]
            M1[(Master A)]
            R1[(Replika A)]
            M1 -.replikacja.-> R1
        end
        subgraph Shard2[Shard 2: sloty 5461-10922]
            M2[(Master B)]
            R2[(Replika B)]
            M2 -.replikacja.-> R2
        end
        subgraph Shard3[Shard 3: sloty 10923-16383]
            M3[(Master C)]
            R3[(Replika C)]
            M3 -.replikacja.-> R3
        end
    end
    Klient -->|CRC16 - kieruj do slotu| M1
    Klient --> M2
    Klient --> M3
    M1 <-.gossip.-> M2
    M2 <-.gossip.-> M3
    M1 <-.gossip.-> M3

Materiały

21. Czym jest sharding w Redis Cluster (16384 slotów)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
22. Jak Redis Cluster obsługuje failover i rebalansowanie?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Pub/Sub i kolejki wiadomości

23. Czym jest mechanizm Pub/Sub w Redis i jak działa?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
24. Jakie są ograniczenia Redis Pub/Sub (brak persystencji, at-most-once delivery)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
25. Jak zaimplementować kolejkę zadań przy użyciu listy (LPUSH/BRPOP)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
26. Kiedy używać Streams zamiast Pub/Sub do przesyłania wiadomości?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Strategie cacheowania

27. Jakie są typowe wzorce cache'owania (cache-aside, write-through, write-behind)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
28. Czym jest cache invalidation i jakie ma strategie (TTL, manual, event-based)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
29. Jak zaimplementować cache stampede prevention (request coalescing)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
30. Co to jest "thundering herd problem" i jak go uniknąć w Redis?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
31. Jak działa LRU/LFU eviction w Redis i kiedy które wybrać?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Wydajność i optymalizacja

32. Jak monitorować wydajność Redis (INFO, MONITOR, SLOWLOG)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
33. Czym jest pipelining i jak zmniejsza latencję wielu operacji?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
34. Czym są transakcje MULTI/EXEC i jakie mają ograniczenia?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
35. Jak optymalizować zużycie pamięci w Redis (encoding, struktury embedded)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
36. Jakie są typowe przyczyny wolnych operacji w Redis i jak je diagnozować?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Bezpieczeństwo

37. Jak zabezpieczyć Redis w produkcji (AUTH, ACL, bind, firewall)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
38. Czym jest Redis ACL i jak różni się od starszego AUTH (requirepass)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
39. Jak włączyć szyfrowanie TLS dla połączeń Redis?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
40. Jakie są typowe podatności Redis (RCE, unauthorized access)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Transakcje i skrypty Lua

41. Jak działają transakcje w Redis (MULTI, EXEC, DISCARD, WATCH)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
42. Czym różnią się transakcje Redis od ACID w bazach relacyjnych?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
43. Jak używać skryptów Lua w Redis (EVAL, EVALSHA) i kiedy je stosować?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
44. Czym jest optimistic locking z użyciem WATCH/MULTI/EXEC?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Use cases i wzorce projektowe

45. Jak zaimplementować rate limiting w Redis (token bucket, sliding window)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
46. Jak używać Redis do sesji użytkowników w aplikacji webowej?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
47. Jak działa distributed lock w Redis (Redlock, SET NX EX)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
48. Jak zaimplementować licznik real-time (INCR/DECR) i jakie są pułapki?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
49. Jak używać Redis do leaderboardów (Sorted Set + ZRANGE)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Integracja i klienty

50. Jakie są popularne klienty Redis dla Node.js (ioredis vs node-redis)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
51. Jak skonfigurować connection pool dla Redis w aplikacji Node.js?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
52. Jak obsłużyć błędy połączenia i reconnect w klientach Redis?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
53. Czym jest RedisJSON i RediSearch (Redis Stack modules)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
54. Jak testować kod używający Redis (ioredis-mock, testcontainers)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
55. Jakie są dobre praktyki nazewnictwa kluczy w Redis (namespace, kolony)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Chcesz poznać wszystkie odpowiedzi?

Uzyskaj pełny dostęp do 55 pytań rekrutacyjnych z Redis oraz pozostałych technologii.

Zobacz plany cenowe