Redis

800px-Redis_Logo.svg

Redis je key-value databáze, kde value nemusí být jen ordinální hodnota, ale komplexnější struktura. Největší výhodou Redisu je to, že se jedná o in-memory databázi, což znamená, že vaše data jsou uložena přímo v RAM a práce s nimi je tedy nesrovnatelně rychlejší než s konvenčními databázemi. Tím samozřejmě nechci říct, že nejde nakonfigurovat MongoDB jako in-memory database, ale neni to typický inuse case.

Díky tomuto je Redis přímo předurčen k použití jako uložiště pro session proměnné www serveru, nebo čehokoliv jiného. Takto Redis primárně používám já. Session jsou proměnné které si mezi sebou vyměňuje klientův prohlížeč na straně jedné a vaše webová backend aplikace na straně serveru. A tou může být například NodeJS aplikace. Typicky Apache i Nginx pro sessions používají disk a data ukládají do souborů na disku. Přesunutím je do Redisu získáváte zrychlení práce se session daty, protože nejsou na pomalém disku, ale v neskutečně rychlejší RAM. Super.

No a jednou se třeba kvůli škálovatelnosti rozhodnote používat nějaký load balancer, jako je Nginx a zátěž (připojující se klienty) budete distribuovat mezi několik fyzických serverů. Super, protože krom samotného rozdělení zátěže získáte i redudantní prostředí, kdy vás neohrozí výpadek některého z vašich serverů, protože jeho práci za něj automaticky přebírají ostatní servery (o distribuci requestů se stará přímo Nginx).

No a přesně tady vyvstává problém: je sice cool, že Nginx pořeší výkon a dostupnost, ale právě vzhledem k tomu, že requesty klientů poletují mezi různými servery a vy v podstatě nevíte který ze serverů bude na daný požadavek odpovídat, musíte nějak pořešit i centrální a distribuované uložiště sessions dat. Protože je vám prd platné, že máte rychlý Redis, když není zrovna dostupný.

Řešením Redis uložiště je pak jeho nakonfingurování jako replica setu, kdy data jsou ukládána na master server a zároveň replikována na slave servery a tím je zajištěna jeji redudance, ale navíc ještě vlastní high availability manager: redis-sentinel, který monitoruje jednotlivé hosty v replica setu a podle jejich dostupnosti, či nedostupnosti, určuje jak se bude s daty pracovat. Redis uložiště se pak jeví jako jediný prostor na jakémkoliv stroji bez ohledu na to, jestli některý z fyzických strojů opradu neběží.

Skvělé: jako celek pak vše vypadá jako tří vrstvá architektůra:

  1. NodeJS aplikace, která komunikuje s redis-sentinelem (NPM balíček, ale i Python modul a víc jsem nezkoušel). Respektive ví o všech instnancích sentinelu
  2. Se samontou aplikací komunikuje redis-sentinel, který ví o všech fyzických Redis instancích a propaguje do aplikací funční master server. Sentinel se stará o monitoring jednolivých Redis serverů. Běží na všcech nodech a komunikují mezi sebou navzájem.
  3. No a úplně vespod jsou samotné instance Redis databáze. Jedna z nich je master a ostatní jsou slave.

Instalace, konfigurace

Osobně vycházím z toho,že mám 3 fyzické stroje, na kterých mi běží Nginx, pod ním na nějakém portu (reverzní proxy cache) NodeJS aplikace s Express web frameworkem, který pro session používa midleware Redis.

Instalace Redisu

sudo dnf install redis # redis-sentinel je soucasti balicku redis (na Fedorer)
sudo systenctl enable redis.service
sudo systemctl start resis.service
sudo systemctl enable redis-sentinel.service
sudo systemctl start redis-sentinel.service

Konfigurace je pak v /etc/redis.conf a /etc/redis-sentinel.conf

Konfigurace

Nejprve je potřeba rozeběhnout jednotlive instance Redis replica setu.

Do /etc/redis.conf na master serveru přídat následující:

daemonize yes
masterauth NejakeSuperHeslo
requirepass NejakeSuperHeslo

Na slave serverech je potřeba ještě přidat informaci o tom, kde je master server:
slaveof IP PORT
Kde IP je ip adresa server na kterém běží master Redis instance.
Defaultní port Redisu je 6379.

Pak stačí všechny Redis instance zrestartovat a přhlásit se k nim pomocí bash příkazu redis-cli:

redis-cli HOST PORT

Protože je zapnutá autorizace, je potřeba zadat auth NejakeSuperHeslo.
Po zapsáni dat na master serveru: set pocitadlo 1, by mělo jít vyčíst počítadlo příkazem get pocitadlo z ostatních slave Redis serverů.

Tímto máme funkční Redis replica set s jedním master serverem a dvěma slave servery.

Nad tímto replica setem spustíme redis-sentinel, který se stará o monitoring jednotlivách serverů v replica setu.
Jediné co je potřeba je doplnit info pro autorizaci a pak info o master serveru:

sentinel monitor mymaster ip port 2
sentinel auth-pass mymsater NejakeSuperHeslo

ip je IP adresa master serveru
mymaster je název redis serveru
2 je počet serverů které musí souhlasit s tím, že master je nedostupný pro zvolení nového mastera

redis-sentinel je potřeba spustit na všech serverech a jako IP adresu uvést IP adresu master serveru dle výchozí konfigurace. Sentinel si dynamciky za provozu bude nastavovat IP master serveru dle dostupnosti jednotlivých serverů.

Připojení se z Python aplikace

from redis.sentinel import Sentinel

IP1 = 'localhost'
IP2 = '192.168.1.1'
IP3 = '192.168.1.2'

sentinel = Sentinel([(IP1, 26379), (IP2, 26379), (IP3, 26379)], socket_timeout=0.1)
master = sentinel.master_for('mymaster', socket_timeout=0.1)

# zapis na masteru
master.set('pocitadlo', 1)

# vycteni na slave serveru
slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
print(slave.get('pocitadlo'))

Redis Sentinel v NodeJS

var Redis = require('ioredis');
var redis = new Redis({
  sentinels: [
    {host: 'localhost', port: 26379},
    {host: '192.168.1.2', port: 26379},
    {host: '192.168.1.3', port: 26379}
  ],
  name: 'mymaster'
});

redis.set('pocitadlo', 1);