Creaiamo un ambiente di test per memcached e testiamolo con perl.
Utilizzeremo:
- memcahced
- perl
- il modulo perl Cache::Memcached
- il modulo perl String::Random
- il comando di monitoraggio memcache-top
Do per scontato che perl sia installato. Questo è, credo, praticamente sempre vero in ambiente UNIX/LInux.
Potrebbe non essere invece presente il modulo perl per la gestione della cache con memcached. Lo si può istallare o come pacchetto dell distribuzione (es. su Debian/Ubuntu qualche cosa come sudo aptitude install libcache-memcached-perl) o come modulo cpan:
$ cpan
cpan[1]> install Cache::Memcached
Analogamente istalliamo il modulo String::Random (libstring-random-perl).
Passiamo ora al daemone.memcached. Consideriamo come sempre un sistema Debian/Ubuntu dove basterà:
# aptitude update # aptitude install memcached # update-rc.d -f memcached remove # /etc/init.d/memcached stop
Il primo comando aggiorna le liste dei pacchetti, il secondo istalla il demone. Dato che stiamo lavorando su di un ambiente di test, con il terzo comando si facciamo in modo che il demone non venga avviato all’avvio del pc e con l’ultimo fermiamo il demone lanciato con le configurazioni di default.
Memcached è presente in quasi tutte le distribuzioni e se non si utilizza un sistema Debian o derivato si può far ricorso al sistema di pacchettizzazione della propria distribuzione o anche ai sorgenti del demone recuperabili dal sito ufficiale.
L’ultimo elemento per l’ambiente di test è memcache-top, che può essere scaricato dal sito ufficiale.
wget -O memcache-top http://memcache-top.googlecode.com/files/memcache-top-v0.6
Ora che abbiamo tutti gli elementi possiamo aprire una shell e avviare 3 demoni per avere un pool non banale. Li metteremo in ascolto su localhost ma, ovviamente, su porte differenti.
/usr/bin/memcached -d -m 64 -p 11211 -u memcache -l 127.0.0.1 /usr/bin/memcached -d -m 64 -p 11212 -u memcache -l 127.0.0.1 /usr/bin/memcached -d -m 64 -p 11213 -u memcache -l 127.0.0.1
possimao poi avviare in un’altra shell memcache-top con cui monitereremo il nostro pool di server
memcache-top --commands --instance=127.0.0.1:11211,127.0.0.1:11212,127.0.0.1:11213
Vediamo ora un primo semplice script perl che chiameremo memcahced.pl:
#!/usr/bin/perl -w use strict; use Cache::Memcached; my $memd = new Cache::Memcached { 'servers' => [ "localhost:11211", "localhost:11212", "localhost:11213" ], 'debug' => 0, 'compress_threshold' => 10_000, }; $memd->set("my_key", "Some Value\n"); my $val = $memd->get("my_key"); if ($val) { print $val; }
In dettaglio:
#!/usr/bin/perl -w
use strict;
use Cache::Memcached;
Richiama l’eseguibile attivando i warning e i moduli strict e Memcached.
my $memd = new Cache::Memcached {
'servers' => [ "localhost:11211", "localhost:11212", "localhost:11213" ],
'debug' => 0,
'compress_threshold' => 10_000,
};
definisce l’oggetto di connessione a memcached inserendo una lista di server.
$memd->set("my_key", "Some Value\n"); my $val = $memd->get("my_key"); if ($val) { print $val; }
scrive una chiave su memcached e la rilegge andando poi a scrivere a video il risultato.
Per eseguire questo script non bisogna dimenticare di rendere eseguibile il file o richiamarlo esplicitamente con l’interprete perl.
Con una singola esecuzione memcache-top non dice gran che ma se si esegue ripetutamente lo script ad esempio con
while [ true ]; do ./memcached.pl ; done
si vedranno numerosi accessi ad un singolo server; come ci si sarebbe dovuti aspettare trattandosi di una sola chiave.
Nel mio caso memcahce-top riporta:
memcache-top v0.6 (default port: 11211, color: on, refresh: 3 seconds) INSTANCE USAGE HIT % CONN TIME EVICT/s GETS/s SETS/s READ/s WRITE/s 127.0.0.1:11211 0.0% 0.0% 5 1.0ms 0.0 0 0 2 344 127.0.0.1:11212 0.0% 0.0% 5 0.8ms 0.0 0 0 2 344 127.0.0.1:11213 0.0% 0.0% 5 0.6ms 0.0 14 14 647 992 AVERAGE: 0.0% 0.0% 5 0.8ms 0.0 5 5 217 560 TOTAL: 83B/ 0.2GB 15 2.4ms 0.0 14 14 651 1680 (ctrl-c to quit.)
ma soprattutto dopo aver ucciso il demone in ascolto sulla porta 11213
memcache-top v0.6 (default port: 11211, color: on, refresh: 3 seconds) INSTANCE USAGE HIT % CONN TIME EVICT/s GETS/s SETS/s READ/s WRITE/s 127.0.0.1:11211 0.0% 0.0% 5 0.6ms 0.0 0 0 2 344 127.0.0.1:11212 0.0% 0.0% 5 0.4ms 0.0 15 15 662 1007 127.0.0.1:11213 is DOWN. AVERAGE: 0.0% 0.0% 3 0.3ms 0.0 5 5 221 450 TOTAL: 83B/ 0.1GB 10 1.0ms 0.0 15 15 664 1351 (ctrl-c to quit.)
dove so vede che le connessioni si sono spostate su di un’altro demone. Su questo aspetto bisogna fare molta attenzione dato che in un sistema di produzione la gestione dei fault è cruciale e dato che questo aspetto è demandato alla libreria del linguaggio che si utilizza bisogna averne molto chiaro il comportamento. Vale comunque in generale che bisognerebbe avere in numero sufficiente di server per cui se se ne dovesse perdere uno i restanti dovrebbero essere sufficienti a svolgere i loro compiti; in altre parole è molto meglio distribuire il servizio su molti serevr che averne uno o due dedicati.
Per vedere in che modo le chiavi si distribuiscono sul cluster ora inseriamo un valore fisso in una chiave di nome casuale (la distribuzione è legata al nome della chiave). Per farlo utilizziamo un altro script perl che chiameremo memcahced_random.pl:
#!/usr/bin/perl -w use strict; use Cache::Memcached; use String::Random; my $memd = new Cache::Memcached { 'servers' => [ "localhost:11211", "localhost:11212", "localhost:11213" ], 'debug' => 0, 'compress_threshold' => 10_000, }; my $foo = new String::Random; my $random_key = $foo->randpattern("..."); my $value = "chiave casuale"; $memd->set("$random_key", "$value\n"); my $val = $memd->get("$random_key"); if ($val) { print $val; }
Non è molto diverso dal precedente tranne nella riga:
my $random_key = $foo->randpattern("...");
in cui viene generata casualmente una stringa di 3 caratteri da utilizzare come nome della chiave.
Anche in questo caso conviene inserire lo script in un loop per visualizzarne meglio gli effetti con memcache-top:
while [ true ]; do ./memcached_random.pl; done
Le connessioni si andranno a distribuire sui vari nodi in modo ragionevolmente equilibrato
memcache-top v0.6 (default port: 11211, color: on, refresh: 3 seconds) INSTANCE USAGE HIT % CONN TIME EVICT/s GETS/s SETS/s READ/s WRITE/s 127.0.0.1:11211 0.1% 0.0% 5 0.9ms 0.0 7 7 317 686 127.0.0.1:11212 0.1% 0.0% 5 0.6ms 0.0 9 9 375 748 127.0.0.1:11213 0.1% 0.0% 5 0.6ms 0.0 9 9 403 779 AVERAGE: 0.1% 0.0% 5 0.7ms 0.0 8 8 365 738 TOTAL: 132.7KB/ 0.2GB 15 2.2ms 0.0 25 25 1095 2213 (ctrl-c to quit.)