Redis depuis PHP
Voici un petit récapitulatif des différents moyens d'utiliser une base de données Redis depuis PHP sous Linux
L'ensemble des tests ont été réalisés sous Fedora 25 mais devrait fonctionner avec RHEL, CentOS ou une autre distribution.
Solution testées:
- Extension redis (voir #1)
- Bibliothèque Predis (voir #2)
- Extension phpiredis (voir #3)
- Bibliothèque Predis avec l'extension phpiredis (voir #4)
Pour chaque solution, j'ai utilisé 3 jeux d'essai (lancé une dizaine de fois pour avoir une valeur moyenne)
- connexion et incrément d'une valeur, uniquement pour mesurer le coût de la connexion
- connexion et set / get de 10000 valeurs numériques
- connexion et set / strlen de ~2700 valeurs importantes (l'ensemble des pages de man 1)
1. Extension redis
Composants nécessaires :
- Extension redis
- Paquets RPM: php-pecl-redis
Exemple de code :
<?php $time = microtime(true); $redis = new Redis(); $redis->connect('127.0.0.1', 6379); printf("Value = %d\\n", $redis->incr("foo")); $time = microtime(true)-$time; printf("Done in %.6f\\n", $time);
Résultats :
- Connexion : 0.000299
- Set / get : 0.277000
- Set / strlen : 0.110900
C'est la solution la plus connue est la plus utilisée, j'ai malheureusement de gros doute sur la qualité du code actuel de l'extension.
2. Bibliothèque Predis
Composants nécessaires:
- Bibliothèque Predis
- Paquets RPM: php-nrk-Predis
Exemple de code :
<?php require 'Predis/Autoloader.php'; Predis\\Autoloader::register(); $time = microtime(true); $redis = new Predis\\Client(['host' => '127.0.0.1', 'port' => 6379]); printf("Value = %d\\n", $redis->incr("foo")); $time = microtime(true)-$time; printf("Done in %.6f\\n", $time);
Code complet utilisé pour les tests predis.txt (en décommentant l'appel au constructeur).
Résultats :
- Connexion : 0.001890
- Set / get : 0.375500
- Set / strlen : 11.445000
Rien d'étonnant à ce qu'une implémentation pure PHP soit nettement plus lente. C'est évidement le chargement de la bibliothèque qui pénalise la connexion, ensuite l'exécution de requêtes simples (get/set) reste très acceptable.
3. Extension phpiredis
Composants nécessaires:
- Extension phpiredis
- Paquets RPM: php-phpiredis, hiredis
Exemple de code :
<?php $time = microtime(true); $redis = phpiredis_connect('127.0.0.1', 6379); printf("Value = %d\\n", phpiredis_command($redis, "INCR foo")); $time = microtime(true)-$time; printf("Done in %.6f\\n", $time);
Code complet utilisé pour les tests : phpiredis.txt.
Résultats :
- Connexion : 0.000241
- Set / get : 0.288100
- Set / strlen : 0.105000
Les résultats sont comparables à ceux de l'extension redis.
Il est dommage que cette extension, pourtant ancienne, soit toujours en phase de développement (beta). Le code très simple (~1000 lignes contre ~20000 pour redis), et utiliser la bibliothèque hiredis me semble beaucoup plus sain et maintenable à long terme.
4. Bibliothèque Predis avec l'extension phpiredis
Composants nécessaires:
Exemple de code :
<?php require 'Predis/Autoloader.php'; Predis\\Autoloader::register(); $time = microtime(true); $redis = new Predis\\Client(['host' => '127.0.0.1', 'port' => 6379], ['connections' => ['tcp' => 'Predis\\\\Connection\\\\PhpiredisSocketConnection']]); printf("Value = %d\\n", $redis->incr("foo")); $time = microtime(true)-$time; printf("Done in %.6f\\n", $time);
Code complet utilisé pour les tests predis.txt.
Résultats :
- Connexion : 0.001795
- Set / get : 0.378900
- Set / strlen : 0.145300
Comme indiqué dans la documentation, la bibliothèque Predis est largement optimisée en utilisant l'extension phpiredis pour les données importantes. Les résultats des tests sont donc très acceptables.
5. Conclusion
À vous de faire votre choix à la lecture des résultats.
J'aurais tendance à privilégier l'extension phpiredis lorsque la vitesse est une priorité absolue, et la bibliothèque Predis pour la beauté du code. Ce couple suivant une rationalisation aussi suivi par d'autres projets (e.g. mongo => mongodb) ou l'extension est réduite au minimum en utilisant une bibliothèque dédiée (ici hiredis) et se charge uniquement de la partie bas niveau, là où les perfornances sont nécessaires, la bibliothèque fournissant la partie haut niveau au développeur.
Je prévois d'aider l'auteur de l'extension phpiredis pour qu'une version soit publié, et si possible sur la forge PECL afin de lui donner la visiblité qu'elle me semble mériter. Alors je soumettrais probablement une revue pour les dépôts officiels de Fedora/EPEL.