Laravel 5 oferuje prosty i elastyczny mechanizm obsługi pamięci cache. Od klasycznego opartego o system plików, przez bazę danych, aż po mechanizmy bazujące na pamięci - Memcached i Redis. Na szczególną uwagę zasługują te dwa ostatnie.

Różnice pomiędzy tymi dwoma usługami są dobrze opisane, zalety i wady każdego z nich bez problemu odszukacie w Sieci. Generalnie Redis cieszy się zasłużoną opinią lepszego - jest bardziej wydajny, uniwersalny i niezawodny. Jednak decyzja, który z nich wybrać jest powiązana z rodzajem aplikacji, którą ma wspierać.

Dla stron z dominującymi treściami statycznymi, gdzie aktualizacje są sporadyczne, a struktury niezbyt skomplikowane (memcached serializuje przechowywane obiekty), memcached będzie dobrym i wystarczającym rozwiązaniem. Także tam, gdzie ilość treści jest bardzo duża. Współcześnie większość dystrybycji Linuxa i innych *nixów ma tę usługę dostępną z klucza, a nawet jeżeli tak nie jest, to instalacja z pakietów jest banalna.

Jeżeli jednak chcemy z pamięci cache korzystać przy bardziej skomplikowanych i dynamicznych projektach, w których planujemy w cache przechowywać obiekty o różnych właściwościach i typach (sie tylko string), to zdecydowanie Redis wykazuje tu swoją przewagę.

Instalacja serwera Redis

(za Digital Ocean)

W środowisku Ubuntu pakiet możemy zainstalować klasycznie używając:

sudo add-apt-repository ppa:chris-lea/redis-server
sudo apt-get update
sudo apt-get install redis-server

Jednak warto w tym przypadku istalację wykonać ze źródeł i może to wyglądać tak:

$ sudo apt update
$ sudo apt full-upgrade
$ sudo apt install build-essential tcl

#pobranie najnowszej wersji stabilnej
$ curl -O http://download.redis.io/redis-stable.tar.gz 

#rozpakowanie do katalogu redis-stable
$ tar xzvf redis-stable.tar.gz 

#instalacja
$ cd redis-stable
$ make
$ make test
$ sudo make install

Konfiguracja

Jeżeli wszystko zakończy się powodzeniem, to możemy przystąpić do podstawowej konfiguracji.

#tworzymy katalog, w którym będą nasze pliki konfiguracyjne
$ sudo mkdir /etc/redis

#kopiujemy wzorcowy plik konfiguarcji dostarczony z pakietem
$ sudo cp /ścieżka-do-źródła/redis-stable/redis.conf /etc/redis

#otwieramy w edytorze
$ sudo nano /etc/redis/redis.conf

Teraz wprowadzimy tylko dwie zmiany:

# 1. odszukujemy linię z parametrem "supervised" i nadajemy mu wartość "systemd"

. . .

# If you run Redis from upstart or systemd, Redis can interact with your
# supervision tree. Options:
#   supervised no      - no supervision interaction
#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode
#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
#   supervised auto    - detect upstart or systemd method based on
#                        UPSTART_JOB or NOTIFY_SOCKET environment variables
# Note: these supervision methods only signal "process is ready."
#       They do not enable continuous liveness pings back to your supervisor.
supervised systemd

. . .

# 2. odszukujemy linię z parametrem "dir" (working directory) i przypisujemy mu ścieżkę w naszym systemie plików

. . .

# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir /var/lib/redis

. . .

Po wykonaniu tych dwóch zmian nasz serwer Redis jest właściwie gotowy do pracy. Pozostało nam jeszcze zadbać o jego automatyczne uruchomianie. Do tego celu zgodnie z wcześniejszym wpisem w pliku konfiguracyjnym, użyjemy systemd:

#tworzymy plik startowy w katalogu /etc/systemd/system/ (Ubuntu)
$ sudo nano /etc/systemd/system/redis.service

#i umieszczamy w nim wymagane definicje
[Unit]
Description=Redis Cache Server
After=network.target

[Service]
User=redis
Group=redis
ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf
ExecStop=/usr/local/bin/redis-cli shutdown
Restart=always

[Install]
WantedBy=multi-user.target

Pozostało nam jeszcze stworzenie dedykowanego użytkownika i grupy oraz utworzenie katalogu roboczego, którego ścieżkę podaliśmy w pliku konfiguracyjnym.

$ sudo adduser --system --group --no-create-home redis
$ sudo mkdir /var/lib/redis
$ sudo chown redis:redis /var/lib/redis
$ sudo chmod 770 /var/lib/redis

Uruchomienie i testy

Dotarliśmy do końca procesu instalacji, możemy uruchomić nasz serwer Redis i go przetestować.

# uruchomienie ręczne
$ sudo systemctl start redis

# sprawdzamy status
$ sudo systemctl status redis

Jeżeli wszysko jest ok, to otrzymamy taki komunikat:

● redis.service - Redis In-Memory Data Store
   Loaded: loaded (/etc/systemd/system/redis.service; enabled; vendor preset: enabled)
   Active: active (running) since pon 2018-05-07 03:13:43 CEST; 13h ago
 Main PID: 23562 (redis-server)
   CGroup: /system.slice/redis.service
           └─23562 /usr/local/bin/redis-server 127.0.0.1:6379

Zadowoleni możemy jeszcze sprawdzić działanie używając do tego celu narzedzia redis-cli:

$ redis-cli
$ 127.0.0.1:6379> set test "Działa !!!"
$ OK
$ 127.0.0.1:6379> get test
$ Działa !!!
$ exit

Pozostało jeszcze przystosowanie serwera Redis do automatycznego uruchamiania.

$ sudo systemctl enable redis

Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /etc/systemd/system/redis.service.

I to wszystko, serwer jest gotowy do działania. Jeżeli planujemy korzystać z jego zalet w projektach PHP, to na początek warto zapoznać się z tym artykułem, który w prostych żołnierskich słowach opisuje pierwsze kroki. Zresztą serwer Redis ma imponującą dokumentację, a w Sieci bez problemu można znaleźć porady na każdy temat z nim związany.

Laravel i Redis

Mając poprawnie skonfigurowany serwer Redis możemy korzystać z jego usług w swoich projektach Laravel. Tradycyjnie, konfiguracja jest prosta i logiczna, odbywa się w dwóch krokach:

1. Plik config/cache.php

Otwieramy w edytorze i odszukujemy w sekcji "sotres" pozycję "redis":

'redis' => [
    'driver' => 'redis',
    'connection' => 'default',
],

# i definiujemy np. dwa nowe "magazyny"

'redis-model' => [
    'driver' => 'redis',
    'connection' => 'model-cache',
],

'redis-responsecache' => [
    'driver' => 'redis',
    'connection' => 'response-cache',
],

Nazwy identyfikują kolejne bazy danych serwera Redis, których bedziemy uzywali do różnych celów. Dzięki temu zyskamy dodatkową elastyczność przy zarządzaniu zawartością cache z poziomu naszych skryptów - działania w odrębnych bazach danych są niezależne, nie wpływają na zasoby przechowywane w innych.

W powyższym przykładzie 'redis' jest magazynem podstawowym, a dwa kolejne zostały utworzenie w celu przypisania ich do:

  1. przechowywania modeli (pakiet Laravel-model-caching)
  2. przechowywania odpowiedzi żądań GET (pakiet Laravel-responsecache)

2. Plik config/database.php

Teraz musimy jeszcze zdefiniować bazy danych powiązane z magazynami. Otwieramy plik w edytorze, odszukujemy sekcję "redis" i do definicji domyślej dopisujemy dwie kolejne skojarzone z nazwami zapisanymi w poprzednim kroku:

'redis' => [

    'client' => 'predis',

    'default' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port' => env('REDIS_PORT', 6379),
        'database' => 0,
    ],

    'model-cache' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port' => env('REDIS_PORT', 6379),
        'database' => 1,
    ],

    'response-cache' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port' => env('REDIS_PORT', 6379),
        'database' => 2,
    ],

],

Ważne jest nadanie wartości parametrom 'database', nie muszą być kolejne, ważne, żeby były różne.

I to by było na tyle. Dzięki takiej konfiguracji zyskujemy możliwość korzystania z szybkiego i wydajnego mechanizmu cache, do którego w swoich skryptach mamy dostęp na kilka sposobów, w tym także bezpośrednio, co dobrze opisane jest w dokumentacji. Możemy oczywiście zdefiniować w globalnej konfiguracji serwer Redis jako podstawowy cache - wystarczy zmienić odpowiednie wartości w pliku .env. Możemy także dać dostęp pakietom, które mogą na tym skorzystać, jak np. te dwa opisane przeze mnie powyżej.

Po uruchomieniu możemy sprawdzić status Redis poleceniem info:

$ redis-cli

127.0.0.1:6379>info

# Server
redis_version:4.0.9
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:7478e950d9b8196
redis_mode:standalone
os:Linux 3.14.32-xxxx-grs-ipv6-64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:5.4.0
process_id:23562
run_id:4ccad9419e3a4a46dc4e5b36e4f7dfef059b6c22
tcp_port:6379
uptime_in_seconds:52900
uptime_in_days:0
hz:10
lru_clock:15759083
executable:/usr/local/bin/redis-server
config_file:/etc/redis/redis.conf
...
...
...
# CPU
used_cpu_sys:25.01
used_cpu_user:12.47
used_cpu_sys_children:0.12
used_cpu_user_children:1.25

# Cluster
cluster_enabled:0

# Keyspace
db0:keys=5,expires=0,avg_ttl=0
db1:keys=192,expires=0,avg_ttl=0
db2:keys=2,expires=0,avg_ttl=0

Na pożegnanie

Jak widać, instalacja nie jest szczególnie wymagająca, w kilka minut można tchnąć nowe życie w nasz projekt. Warto spróbować.


blog comments powered by Disqus