Mit einem Redis-Cluster steht ein über mehrere Gateways verteilte ausfallsicherer Datenspeicher zur Verfügung. Ein Wert kann dann z.B. wie folgt geschrieben werden:
redis-cli -c -p 7000 set gate01-exit-provider earthvpn
Der Speicher ist den Gateways (bzw. zukünftig auch Servern) vorbehalten. Ein Zugriff von den Knoten oder gar den Clients ist nicht vorgesehen.
Aktuell eingesetzte Version: 3.2.11
Die Version 4 werden wir erst einsetzen, wenn die Server auf Debian Buster (10) gewechselt sind.
Der Download der Quellen befindet sich unter: http://redis.io/download/, die jeweils aktuelle Version unter http://download.redis.io/.
Benötigte Pakete:
aptitude install ruby libjemalloc1 php-redis python-redis
Wir wollen die aktuelle, clusterfähige Version haben, also übersetzen wir uns das Ding einfach selber:
cd /usr/local/src wget http://download.redis.io/redis-stable.tar.gz tar xvzf redis-stable.tar.gz cd redis-stable make make install gem install redis
Überprüfen, ob alles geklappt hat
redis-server --version
Benutzer anlegen:
adduser --system --group --disabled-password --home /var/lib/redis --gecos 'Redis Server' redis
vm.overcommit_memory=1
# redis-server configure options # ULIMIT: Call ulimit -n with this argument prior to invoking Redis itself. # This may be required for high-concurrency environments. Redis itself cannot # alter its limits as it is not being run as root. (default: do not call # ulimit) # # ULIMIT=65536 # Options for Freifunk Community Pinneberg # RUN_DAEMON=yes|no RUN_DAEMON="yes"
Das für den Redis-Server vorhandene Init-Script bzw. deren Varianten die im Netz zu finden sind, sind irgendwie alle nicht überzeugend und können auch keine Cluster mit mehreren Instanzen je Server verwalten. Aus diesem Grund gibt es hier eine neu entwickelte Variante. Da sie sowohl mit Standalone-Servern als auch mit Clustern umgehen kann, nennen wir sie redis-cluster:
Init-Script, zu finden in den ffpi-tools
Zusätzlich: redistats: https://github.com/jimeh/redistat
Achtung, die folgenden Einträge sind nur als eine Art Notizzettel gedacht und stellen keine freigegebene Anleitung dar.
Anlegen der benötigten Verzeichnisse
mkdir /etc/redis chgrp redis /etc/redis chmod g+w /etc/redis mkdir /var/run/redis chown redis. /var/run/redis mkdir /var/lib/redis mkdir /var/lib/redis/7000 mkdir /var/lib/redis/7001 chown -R redis. /var/lib/redis mkdir /var/log/redis chown redis. /var/log/redis
Wir setzen einen Cluster mit 4 Servern auf: gate01
, gate03
, gate04
und gate05
. Auf jedem der Server läuft ein Master (Port 7000) und ein Slave (Port 7001).
Die folgenden Konfiguratonsbeispiele beziehen sich auf gate01
, Bei den anderen Servern ist einfach eine andere IP-Adresse zu verwenden.
Wichtig:
logfile
ist bewußt leer. Falls es einmal Probleme gibt, kann dort z.B. /var/log/redis/master.log
eingetragen werden um Debuginformationen zu erhalten.Konfigurationsdatei für den Master
# Redis cluster configuration file (Master) # port 7000 bind 10.137.10.1 127.0.0.1 daemonize yes timeout 0 tcp-keepalive 0 tcp-backlog 96 loglevel notice logfile "" dir /var/lib/redis/7000 pidfile /var/run/redis/master-7000.pid save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename freifunk.rdb databases 16 appendonly yes cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000
Konfigurationsdatei für den Slave
# Redis cluster configuration file (Slave) # port 7001 bind 10.137.10.1 127.0.0.1 daemonize yes timeout 0 tcp-keepalive 0 tcp-backlog 96 loglevel notice logfile "" dir /var/lib/redis/7001 pidfile /var/run/redis/slave-7001.pid save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename freifunk.rdb databases 16 appendonly yes cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000
Der Redis-Cluster läuft im Mesh-VPN. Damit wäre theoretisch Zugriff von jedem Gerät im Freifunk-Netz möglich. Da Redis selber keine Konfigurationsmöglichkeit für die Zugriffssteuerung auf IP-Adreßebene vorsieht, regeln wir das über IP-Tables:
iptables -A INPUT -p tcp --dport 7000 -s 127.0.0.1 -j ACCEPT iptables -A INPUT -p tcp --dport 7000 -s 10.137.10.1 -j ACCEPT iptables -A INPUT -p tcp --dport 7000 -s 10.137.12.1 -j ACCEPT iptables -A INPUT -p tcp --dport 7000 -s 10.137.13.1 -j ACCEPT iptables -A INPUT -p tcp --dport 7000 -s 10.137.14.1 -j ACCEPT iptables -A INPUT -p tcp --dport 7000 -j DROP iptables -A INPUT -p tcp --dport 7001 -s 127.0.0.1 -j ACCEPT iptables -A INPUT -p tcp --dport 7001 -s 10.137.10.1 -j ACCEPT iptables -A INPUT -p tcp --dport 7001 -s 10.137.12.1 -j ACCEPT iptables -A INPUT -p tcp --dport 7001 -s 10.137.13.1 -j ACCEPT iptables -A INPUT -p tcp --dport 7001 -s 10.137.14.1 -j ACCEPT iptables -A INPUT -p tcp --dport 7001 -j DROP iptables -A INPUT -p tcp --dport 17000 -s 127.0.0.1 -j ACCEPT iptables -A INPUT -p tcp --dport 17000 -s 10.137.10.1 -j ACCEPT iptables -A INPUT -p tcp --dport 17000 -s 10.137.12.1 -j ACCEPT iptables -A INPUT -p tcp --dport 17000 -s 10.137.13.1 -j ACCEPT iptables -A INPUT -p tcp --dport 17000 -s 10.137.14.1 -j ACCEPT iptables -A INPUT -p tcp --dport 17000 -j DROP iptables -A INPUT -p tcp --dport 17001 -s 127.0.0.1 -j ACCEPT iptables -A INPUT -p tcp --dport 17001 -s 10.137.10.1 -j ACCEPT iptables -A INPUT -p tcp --dport 17001 -s 10.137.12.1 -j ACCEPT iptables -A INPUT -p tcp --dport 17001 -s 10.137.13.1 -j ACCEPT iptables -A INPUT -p tcp --dport 17001 -s 10.137.14.1 -j ACCEPT iptables -A INPUT -p tcp --dport 17001 -j DROP iptables-save > /etc/iptables/rules.v4
Damit die Anzeige von iptables besser lesbar ist, kann die Datei /etc/services
angepaßt werden:
redis 7000/tcp # Redis server redis 7001/tcp redis-cluster 17000/tcp # Redis cluster bus redis-cluster 17001/tcp
/etc/init.d/redis-cluster start
cd /usr/src/redis-stable ./src/redis-trib.rb create --replicas 1 \ 10.137.10.1:7000 10.137.10.1:7001 \ 10.137.12.1:7000 10.137.12.1:7001 \ 10.137.13.1:7000 10.137.13.1:7001 \ 10.137.14.1:7000 10.137.14.1:7001
redis-cli -p 7000 ping redis-cli -p 7000 > set mykey somevalue > get mykey ./src/redis-trib.rb info 10.137.10.1:7000
Achtung: Das ist nur ein Merker für das grobe Vorgehen und ist ggf. fehlerhaft. Beim Slave ist die erste Adresse/Port die lokale Instanz und die Zweite der zu verwendende Master
./src/redis-trib.rb add-node 10.137.12.1:7000 ./src/redis-trib.rb add-node --slave 10.137.12.1:7001 10.137.10.1:7000
./src/redis-trib.rb reshard ...
/etc/init.d/redis-cluster stop
rm /var/lib/redis/7000/* rm /var/lib/redis/7001/*
cluster forget 11de37b1018dbd8a83fa6000af6381630468e01e
cluster nodes
cluster info
cluster failover
– Master/Slave tauschen, Befehl auf einem Slave eingebeninfo server
– allg Info zum aktuellen Serverinfo replication
info cluster
cd /usr/local/src rm redis-stable.tar.gz rm -R redis-stable wget http://download.redis.io/redis-stable.tar.gz tar xvzf redis-stable.tar.gz cd redis-stable make make install gem install redis /etc/init.d/redis-cluster restart
Wenn man gem install redis
mehrfach durchgeführt hat, sind nach einiger Zeit unterschiedliche Versionen installiert. Man kann sich das anzeigen lassen:
gem list redis
Eine alte Version kann gezielt entfernt werden
gem uninstall redis --version 3.2.2
Ebenso kann man sich eine spezielle Version installieren:
gem install redis --version 3.3.5
Eine Übersicht über die verfügbaren Versionen kann man erhalten mit:
gem list ^redis$ --remote --all
Wenn die Client-Software nicht auf einem der Clusterknoten läuft, ist diesem Server die Zugriffsberechtigung mittels Firewallregeln auf allen(!) Clusterknoten zu erteilen.
Beispiel für manuelles, nachträgliches EInfügen:
iptables -I INPUT <pos1> -s <serverip>/32 -p tcp -m tcp --dport 7000 -j ACCEPT iptables -I INPUT <pos2> -s <serverip>/32 -p tcp -m tcp --dport 7001 -j ACCEPT
Basisvoraussetzung:
apt-get install python-hiredis
Um mit dem Cluster zu sprechen, kann man beispielsweise redis-py-cluster verwenden: https://pypi.python.org/pypi/redis-py-cluster/1.3.3 bzw. unter https://github.com/Grokzen/redis-py-cluster
Voraussetzung dafür ist redis-py, unter Debian heißt das Paket python-redis
.
Wenn die Geo-Funktionen genutzt werden sollen, muß die neueste Version von Github
verwendet werden. Aus diesem Grund ist in den folgenen Anweisungen auch kein
Checkout für einen Tag angegeben, es wird der Master verwendet (auf eigene Gefahr).
cd /usr/local/src git clone https://github.com/andymccurdy/redis-py.git cd redis-py cp -a redis /usr/local/lib/python2.7/dist-packages/ bzw. für Python 3 cp -a redis /usr/local/lib/python3.4/dist-packages/ cd /usr/local/src git clone https://github.com/Grokzen/redis-py-cluster.git cd redis-py-cluster git checkout 1.3.3 cp -a rediscluster/ /usr/local/lib/python2.7/dist-packages/ bzw. für Python 3 cp -a rediscluster/ /usr/local/lib/python3.4/dist-packages/
Auf dem Server A:
from rediscluster import StrictRedisCluster startup_nodes = [{"host": "127.0.0.1", "port": "7000"}] rc = StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True) rc.set("freifunk", "pinneberg")
Auf dem Server B:
from rediscluster import StrictRedisCluster startup_nodes = [{"host": "127.0.0.1", "port": "7000"}] rc = StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True) print(rc.get("freifunk"))
Es gibt verschiedene Clients, jedoch funktionieren nicht alle mit dem
Cluster. Unter Debian Jessie funktioniert libphp-predis
.
Um Zugriff auf die Geo-Funktionen zu erhalten, sollte eine aktuelle
Version, wie z.B. 1.1.1 installiert werden. Dieses kann z.B. über PEAR
(siehe http://pear.nrk.io/) erfolgen.
Beispiel
require 'Predis/Autoloader.php'; Predis\Autoloader::register(); $parameters = ['tcp://127.0.0.1:7000']; $options = ['cluster' => 'redis', 'profile' => '3.2']; $client = new Predis\Client($parameters, $options); echo "Statistiken\n"; echo "Knotenanzahl=". $client->get("nodes:counter:total") . "\n"; echo "davon online=".$client->get("nodes:counter:online"). "\n"; echo "davon Gates=".$client->get("nodes:counter:gates"). "\n"; echo "Geo-Funktionen\n"; print_r($client->geopos("nodes:geo", "6466b3c3ac82"));