Kas yra Redis ir kodėl jis toks populiarus
Redis – tai ne tiesiog dar viena duomenų bazė, kurią kažkas sugalvojo, nes jam buvo nuobodu. Tai viena iš tų technologijų, kuri išsprendžia labai konkrečias problemas ir daro tai neįtikėtinai greitai. Pavadinimas kilo iš „Remote Dictionary Server”, ir tai puikiai apibūdina esmę – tai serveris, kuris laiko duomenis atmintyje kaip raktų-reikšmių porą.
Pagrindinis Redis pranašumas – greitis. Kadangi visi duomenys laikomi operatyviojoje atmintyje (RAM), o ne diske, duomenų pasiekimo laikas matuojamas mikrosekundėmis, o ne milisekundėmis. Tai milžiniškas skirtumas, kai jūsų aplikacija apdoroja tūkstančius užklausų per sekundę.
Redis buvo sukurtas 2009 metais italų programuotojo Salvatore Sanfilippo, kuris tiesiog norėjo greičiau apdoroti duomenis savo realaus laiko analitikos projekte. Dabar jį naudoja tokie gigantai kaip Twitter, GitHub, Snapchat, Stack Overflow ir daugybė kitų kompanijų, kurioms svarbus našumas.
Kur Redis tikrai praverčia
Kalbant apie praktinį panaudojimą, Redis puikiai tinka keliose situacijose. Pirmiausia – kešavimas. Jei jūsų aplikacija nuolat kreipiasi į pagrindinę duomenų bazę dėl tų pačių duomenų, Redis gali tapti tarpine grandimi, kuri grąžina duomenis akimirksniu. Pavyzdžiui, populiarios prekės informacija el. parduotuvėje gali būti laikoma Redis, kad kiekvienas vartotojas negautų duomenų iš lėtos SQL bazės.
Sesijų valdymas – dar viena klasikinė Redis panaudojimo sritis. Kai turite daug serverių ir vartotojas gali patekti į bet kurį iš jų, sesijos duomenys turi būti prieinami greitai ir iš bet kurios vietos. Redis puikiai atlieka šį darbą, nes gali nustatyti automatinį duomenų galiojimo laiką (TTL – Time To Live).
Realaus laiko analitika ir skaitikliai taip pat yra Redis stiprybė. Jei norite skaičiuoti puslapio peržiūras, sekti aktyvius vartotojus ar rodyti trending temų sąrašus, Redis atominės operacijos leidžia tai daryti be konkurencijos problemų ir su minimalia vėlave.
Eilės ir pranešimų sistemos – Redis Pub/Sub funkcionalumas leidžia kurti realaus laiko pranešimų sistemas. Tai nėra pilnavertis message broker kaip RabbitMQ ar Kafka, bet daugeliui scenarijų užtenka ir yra paprasčiau įgyvendinti.
Duomenų struktūros, kurios daro Redis išskirtiniu
Skirtingai nuo daugelio kitų key-value duomenų bazių, Redis palaiko įvairias duomenų struktūras, ir tai tikrai keičia žaidimo taisykles. Paprasta string reikšmė – tai tik pradžia.
Lists (sąrašai) leidžia laikyti elementų seką ir efektyviai pridėti ar pašalinti elementus iš pradžios ar pabaigos. Tai idealu eilėms kurti – galite turėti užduočių eilę, kurią darbuotojai (workers) apdoroja vienas po kito.
Sets (aibės) – unikalių elementų kolekcijos, kuriose galite greitai patikrinti, ar elementas egzistuoja, arba atlikti aibių operacijas kaip sąjunga, sankirta ar skirtumas. Pavyzdžiui, galite laikyti visų aktyvių vartotojų ID ir greitai patikrinti, ar konkretus vartotojas yra online.
Sorted Sets (surūšiuotos aibės) – tai kaip paprastos aibės, tik kiekvienas elementas turi balą (score), pagal kurį automatiškai rūšiuojama. Puikus pasirinkimas lyderių lentelėms (leaderboards) ar prioritetinėms eilėms kurti.
Hashes leidžia laikyti objektus su laukais. Vietoj to, kad vartotojo duomenis laikytumėte kaip JSON string, galite laikyti kaip hash su atskirais laukais – name, email, age – ir atnaujinti tik tuos laukus, kurie pasikeitė.
Streams – naujesnis papildymas, skirtas log’ų tipo duomenims, kur svarbi tvarka ir galimybė skaityti duomenis nuo tam tikros pozicijos. Tai kaip supaprastinta Kafka versija Redis viduje.
Kaip pradėti naudoti Redis praktikoje
Įdiegti Redis yra paprasčiau nei daugelis galvoja. Linux sistemose dažniausiai užtenka:
sudo apt-get install redis-server
arba
brew install redis
Mac’e. Po to paleidžiate serverį komanda redis-server, ir jis veikia standartiniame 6379 porte.
Darbui su Redis reikia kliento bibliotekos jūsų programavimo kalbai. Python’e tai būtų redis-py, Node.js – ioredis ar node-redis, PHP – Predis ar phpredis. Visos šios bibliotekos yra brandžios ir gerai dokumentuotos.
Paprastas Python pavyzdys atrodytų taip:
import redis
r = redis.Redis(host='localhost', port=6379, db=0)
r.set('user:1000:name', 'Jonas Jonaitis')
name = r.get('user:1000:name')
print(name.decode('utf-8'))
Kešavimo įgyvendinimas su automatišku galiojimo laiku:
# Išsaugoti duomenis 1 valandai
r.setex('product:555', 3600, json.dumps(product_data))
# Patikrinti ar egzistuoja
if r.exists('product:555'):
data = json.loads(r.get('product:555'))
else:
data = fetch_from_database(555)
r.setex('product:555', 3600, json.dumps(data))
Svarbu suprasti, kad Redis yra single-threaded – vienas procesas apdoroja visas komandas eilės tvarka. Tai reiškia, kad nereikia jaudintis dėl race conditions, bet taip pat reiškia, kad lėtos operacijos gali blokuoti visą serverį.
Persistencija: kaip neišmesti duomenų su vandeniu
Kadangi Redis laiko viską atmintyje, kyla logiškas klausimas – o kas nutinka, kai serveris išsijungia? Redis turi du pagrindinius būdus išsaugoti duomenis diske.
RDB (Redis Database Backup) – tai snapshot’ai, kurie daroma kas tam tikrą laiką arba po tam tikro kiekio pakeitimų. Pavyzdžiui, galite nustatyti, kad snapshot būtų daromas kas 15 minučių, jei buvo bent 100 pakeitimų. Tai efektyvu ir užima mažai vietos, bet galite prarasti naujausius duomenis, jei serveris nutrūksta tarp snapshot’ų.
AOF (Append Only File) – čia kiekviena rašymo operacija įrašoma į failą. Tai lėčiau ir užima daugiau vietos, bet duomenys saugesni. Galite net nustatyti, kad kiekviena operacija būtų nedelsiant įrašyta į diską (fsync always), nors tai labai sulėtins darbą.
Praktikoje daugelis naudoja abu metodus kartu – RDB greitam atsikūrimui ir AOF duomenų saugumui. Redis konfigūracijoje tai atrodo taip:
save 900 1 # Snapshot po 15 min, jei bent 1 pakeitimas
save 300 10 # Snapshot po 5 min, jei bent 10 pakeitimų
save 60 10000 # Snapshot po 1 min, jei bent 10000 pakeitimų
appendonly yes
appendfsync everysec # AOF įrašymas kas sekundę
Bet svarbu suprasti – jei naudojate Redis tik kaip kešą, persistencija gali būti visiškai išjungta. Juk keše prarastus duomenis galima tiesiog vėl užkrauti iš pagrindinės duomenų bazės.
Saugumo ir našumo optimizavimas
Redis iš dėžės nėra labai saugus – jis pasitiki, kad veikia patikimame tinkle. Standartinėje konfigūracijoje net nėra slaptažodžio. Tai puiku development’e, bet production’e būtina:
Nustatyti slaptažodį redis.conf faile:
requirepass jūsų_stiprus_slaptažodis
Apriboti, iš kokių IP adresų galima jungtis:
bind 127.0.0.1 192.168.1.100
Išjungti pavojingas komandas:
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command CONFIG "CONFIG_abc123"
Našumo prasme, Redis jau yra labai greitas, bet yra keletas dalykų, kurie gali padėti:
Connection pooling – vietoj to, kad kiekvienai operacijai kurtumėte naują ryšį, naudokite connection pool’ą. Visos modernios Redis bibliotekos tai palaiko.
Pipelining – jei turite daug komandų, kurios nepriklauso viena nuo kitos, galite jas siųsti vienu metu, o ne laukti kiekvienos atsakymo atskirai. Tai gali 5-10 kartų padidinti throughput.
Atminties optimizavimas – Redis turi įvairių konfigūracijų, kaip efektyviau naudoti atmintį. Pavyzdžiui, maxmemory-policy allkeys-lru automatiškai pašalins seniausius raktus, kai baigiasi atmintis.
Stebėkite Redis našumą su redis-cli --stat arba INFO komanda, kuri parodo detalią statistiką apie atminties naudojimą, komandų skaičių, hit/miss ratio ir daug kitų metrikų.
Redis Cluster ir High Availability
Kai jūsų aplikacija auga, vieno Redis serverio gali nebeužtekti. Čia ateina Redis Cluster ir Sentinel.
Redis Sentinel – tai high availability sprendimas. Jis stebi jūsų Redis master serverį ir, jei šis nutrūksta, automatiškai pakelia vieną iš replica serverių į master rolę. Tai užtikrina, kad jūsų aplikacija nenutrūktų, net jei pagrindinis Redis serveris sugenda.
Redis Cluster leidžia paskirstyti duomenis per kelis serverius (sharding). Duomenys automatiškai paskirstomi pagal hash slot’us – yra 16384 slot’ai, ir kiekvienas serveris atsakingas už tam tikrą jų dalį. Tai leidžia horizontaliai plėstis ir laikyti daugiau duomenų, nei telpa vieno serverio atmintyje.
Cluster’io setup’as nėra trivialus, bet Redis dokumentacija yra gera. Paprasčiausiu atveju jums reikia bent 6 serverių (3 master ir 3 replica). Praktikoje, jei dar nesate pasiekę milijonų užklausų per sekundę, tikriausiai užteks Sentinel setup’o su vienu master ir viena-dviem replikomis.
Svarbus niuansas – ne visos Redis komandos veikia Cluster’yje. Jei operacija apima kelis raktus, kurie gali būti skirtinguose serveruose, gali kilti problemų. Todėl reikia atidžiai planuoti, kaip paskirstysite duomenis.
Alternatyvos ir kada Redis nėra geriausias pasirinkimas
Nors Redis yra puikus įrankis, jis nėra universalus sprendimas visoms problemoms. Yra situacijų, kai vertėtų apsvarstyti alternatyvas.
Jei jums reikia sudėtingų užklausų su JOIN’ais, transakcijų ir ACID garantijų, tradicinė reliacinė duomenų bazė kaip PostgreSQL ar MySQL bus geresnis pasirinkimas. Redis turi transakcijas, bet jos labai primityvios palyginti su SQL duomenų bazėmis.
Kai reikia laikyti didelius duomenų kiekius, kurie netelpa atmintyje, žiūrėkite į MongoDB, Cassandra ar kitas disk-based NoSQL duomenų bazes. Redis Enterprise turi funkcionaliteto, leidžiančio dalį duomenų laikyti diske, bet tai jau nebe open-source versija.
Pilnaverčiam message queue su garantijomis, kad pranešimas bus pristatytas bent kartą, geriau tinka RabbitMQ ar Apache Kafka. Redis Pub/Sub negarantuoja pranešimų pristatymo – jei klientas atsijungęs, pranešimas prarandamas. Redis Streams šiek tiek gerina situaciją, bet vis tiek nėra pilnavertis message broker.
Full-text paieška – čia Redis nėra stiprus, nors ir yra RediSearch modulis. Elasticsearch ar Solr bus galingesni šiam tikslui.
Memcached yra paprastesnė alternatyva, jei jums reikia tik paprasto key-value kešavimo be jokių fancy funkcijų. Jis šiek tiek greitesnis paprasčiausiam kešavimui, bet Redis dažniausiai yra geresnis pasirinkimas dėl savo universalumo.
Ką verta žinoti prieš einant į gamybą
Prieš diegiant Redis production aplinkoje, yra keletas dalykų, kuriuos būtina apgalvoti. Pirmiausia – atminties planavimas. Redis naudoja daugiau atminties nei tiesiog jūsų duomenų dydis. Reikia skaičiuoti su ~1.5-2x overhead’u dėl vidinių struktūrų. Jei turite 10GB duomenų, planuokite 15-20GB RAM.
Monitoring yra kritinis. Naudokite įrankius kaip Redis Commander, RedisInsight ar integruokite su Prometheus/Grafana. Stebėkite šias metricas: atminties naudojimą, evicted keys skaičių, komandų per sekundę, hit/miss ratio, connected clients skaičių.
Backup strategija – net jei naudojate Redis kaip kešą, pagalvokite apie backup’us. RDB failai yra maži ir juos lengva kopijuoti į S3 ar kitą saugyklą. Automatizuokite šį procesą.
Versijų atnaujinimas – Redis komanda išleidžia naujas versijas reguliariai, ir jos dažnai turi svarbių našumo patobulinimų ar saugumo pataisymų. Turėkite planą, kaip atnaujinsite be downtime – čia ir praverčia replica serveriai.
Nepamirškit, kad Redis yra single-threaded, todėl vienas lėtas query gali pristabdyti visą sistemą. Naudokite SLOWLOG komandą, kad pamatytumėte, kurios operacijos užtrunka ilgiausiai. Jei matote, kad KEYS * ar panašios komandos lėtina sistemą, pakeiskite jas į SCAN, kuris dirba iteratyviai ir neblokuoja serverio.
Redis gali būti naudojamas kaip cache-aside, read-through ar write-through keše. Cache-aside – tai kai aplikacija pati valdo, kada rašyti į kešą ir kada skaityti iš jo. Read-through – Redis pats užkrauna duomenis iš šaltinio, jei jų nėra. Write-through – rašoma ir į kešą, ir į pagrindinę bazę vienu metu. Kiekvienas modelis turi savo privalumų ir trūkumų, priklausomai nuo jūsų use case.
Ir paskutinis, bet ne mažiau svarbus dalykas – dokumentuokite savo Redis naudojimo logiką. Po pusės metų nei jūs, nei jūsų komandos nariai nebeatsimins, kodėl tam tikri raktai turi keistą pavadinimų struktūrą ar kodėl TTL nustatytas būtent į 3600 sekundžių. Gera dokumentacija sutaupo daug laiko ir nervų.
Redis yra viena iš tų technologijų, kuri tikrai verta laiko, kuris skiriamas ją išmokti. Ji ne tik išsprendžia konkrečias problemas, bet ir daro tai elegantiškai ir efektyviai. Pradėkite nuo paprastų dalykų – kešavimo ar sesijų valdymo – ir palaipsniui eksperimentuokite su sudėtingesnėmis funkcijomis. Greičiausiai pastebėsite, kad Redis tampa neatsiejama jūsų infrastruktūros dalimi.
