====== Redis-Server ====== 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/. ===== Installation ===== 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: TODO Init-Script, zu finden in den [[ffpi-tools]] Zusätzlich: redistats: https://github.com/jimeh/redistat ===== Cluster-Konfiguration ===== TODO 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: * Bei dem bind Befehl muß die localhost-Adresse an zweiter Stelle stehen. Anderenfalls funktioniert der Cluster nicht. * ''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 ==== Cluster initialisieren ==== * Auf allen beteiligten Servern: /etc/init.d/redis-cluster start * Erstellung anstoßen 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 * Tests redis-cli -p 7000 ping redis-cli -p 7000 > set mykey somevalue > get mykey ./src/redis-trib.rb info 10.137.10.1:7000 ==== Knoten zum Cluster hinzufügen ==== 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 - Knoten aufsetzen ./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 - Slot neu aufteilen ./src/redis-trib.rb reshard ... ==== Knoten vom Cluster entfernen ==== * Prozesse sollten nicht laufen: ''/etc/init.d/redis-cluster stop'' * Verzeichnisse leeren rm /var/lib/redis/7000/* rm /var/lib/redis/7001/* * Auf allen übrigen Serverinstanzen die verwaisten Knoten-IDs entfernen cluster forget 11de37b1018dbd8a83fa6000af6381630468e01e ==== Weitere Cluster-Befehle ==== * ''cluster nodes'' * ''cluster info'' * ''cluster failover'' -- Master/Slave tauschen, Befehl auf einem Slave eingeben * ''info server'' -- allg Info zum aktuellen Server * ''info replication'' * ''info cluster'' ===== Update ===== 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 ===== Ruby Gems ===== 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 ====== Cluster Client ====== 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 -s /32 -p tcp -m tcp --dport 7000 -j ACCEPT iptables -I INPUT -s /32 -p tcp -m tcp --dport 7001 -j ACCEPT ===== Python Cluster Client ===== 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")) ===== PHP Cluster Client ===== 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"));