Pourquoi quitter Redis pour migrer vers SolidQueue
(simplethread.com)- Rails 8 supprime la dépendance à Redis de sa stack par défaut et bascule tous les traitements vers une base de données relationnelle (RDB) via SolidQueue·SolidCache·SolidCable
- Redis est rapide et fiable, mais entraîne une complexité opérationnelle liée à la configuration, la sécurité, la gestion de cluster et les sauvegardes
- SolidQueue s’appuie sur la fonctionnalité PostgreSQL
FOR UPDATE SKIP LOCKEDpour mettre en œuvre un traitement parallèle sans contention - Des fonctionnalités payantes de Redis+Sidekiq comme les tâches récurrentes, le contrôle de concurrence et le tableau de bord de monitoring (Mission Control) sont fournies gratuitement
- Pour la plupart des applications Rails, SolidQueue suffit, et Redis ne reste nécessaire que dans certains cas demandant un traitement temps réel ultra-rapide
Le coût caché de Redis
- Au-delà du simple coût d’hébergement, Redis impose une charge continue de gestion : installation, maintenance, configuration de sécurité, gestion de cluster HA
- Il faut mettre en place la connexion réseau et les règles de pare-feu entre Rails et Redis, l’authentification client et l’orchestration des processus Sidekiq
- En cas d’incident, il faut déboguer simultanément Redis et le SGBDR, avec en plus une stratégie de sauvegarde double
- À l’inverse, une stack Rails sans Redis permet de se contenter de gérer uniquement PostgreSQL, ce qui simplifie l’exploitation
Fonctionnement de SolidQueue
- SolidQueue utilise la fonctionnalité PostgreSQL
FOR UPDATE SKIP LOCKEDafin que plusieurs workers récupèrent des tâches en parallèle sans conflit de verrouillage (lock contention) - Structure principale des tables
solid_queue_jobs: stockage des métadonnées des tâchessolid_queue_scheduled_executions: attente des tâches planifiéessolid_queue_ready_executions: file des tâches prêtes à être exécutées
- Les processus worker, dispatcher, scheduler et supervisor coopèrent en interrogeant périodiquement différentes tables
- Grâce à la conception MVCC de PostgreSQL et à autovacuum, même de gros volumes d’insertions et de suppressions sont traités de manière stable
Planification des tâches récurrentes
- SolidQueue fournit nativement des tâches récurrentes de style cron, configurées dans le fichier
config/recurring.yml - Le scheduler place en file les tâches arrivées à échéance, puis programme automatiquement leur prochaine exécution
- Il s’appuie sur la bibliothèque Fugit pour analyser des plannings en langage naturel, et sur Concurrent::ScheduledTask pour créer des threads
- Il reprend l’approche de planification déterministe de GoodJob, afin de préserver le planning même après redémarrage du processus
Contrôle de concurrence
- SolidQueue utilise le pattern de sémaphore POSIX pour prendre en charge la limitation des exécutions simultanées par tâche
- Exemple : avec
limits_concurrency to: 1, key: ->(user) { user.id }, une seule tâche par utilisateur peut s’exécuter à la fois
- Exemple : avec
- La définition d’une expiration du sémaphore (
duration) permet d’éviter les conflits et les deadlocks - Tables associées
solid_queue_semaphores: suivi des limites de concurrencesolid_queue_blocked_executions: stockage des tâches en attente
Monitoring avec Mission Control
- Mission Control Jobs est un tableau de bord open source gratuit pour Rails 8, qui peut être monté simplement sur la route
/jobs - Fonctionnalités principales
- état des files en temps réel, suivi des tâches en échec, contrôle des retries et de l’abandon
- visualisation de la chronologie des tâches planifiées et récurrentes
- graphiques de débit et de métriques par file
- Les requêtes basées sur SQL permettent une analyse directe dans la base de données sans outil supplémentaire
Migration de Sidekiq vers SolidQueue
- Étape 1 : définir
config.active_job.queue_adapter = :solid_queue - Étape 2 : exécuter
bundle add solid_queue, puisrails solid_queue:installetdb:migrate - Étape 3 : convertir les plannings cron de
sidekiq.ymlversrecurring.yml - Étape 4 : ajouter
jobs: bundle exec rake solid_queue:startauProcfile - Étape 5 : supprimer les gems liées à Redis et Sidekiq
- Le code ActiveJob existant continue de fonctionner sans modification
Cas où Redis reste nécessaire
- traitement soutenu de plusieurs milliers de tâches par seconde
- systèmes temps réel où une latence inférieure à 1 ms est indispensable
- besoin d’une architecture pub/sub complexe ou d’opérations avancées de rate limiting et de compteurs
- Par exemple, Shopify exploite une infrastructure Redis avec 833 requêtes par seconde et 1 172 processus workers
Guide d’implémentation concret
- Lors de la création d’une nouvelle application Rails 8, SolidQueue, SolidCache et SolidCable sont configurés automatiquement
- Il est recommandé de définir dans
config/database.ymlune connexion de base de données distincte pour la queue - Ajouter l’authentification de Mission Control et monter la route
/jobs - Ajouter
jobs: bundle exec rake solid_queue:startdansProcfile.dev, puis lancer l’ensemble avecbin/dev - Après création de tâches de test, leur état peut être vérifié dans Mission Control
Problèmes fréquents et solutions
- Une configuration sur base de données unique est possible, mais réduit la flexibilité en production
- En production, il faut impérativement ajouter une authentification à Mission Control
- Les intervalles de polling par défaut sont de 1 seconde pour les tâches planifiées et de 0,2 seconde pour les tâches immédiates, ce qui convient à la plupart des applications
- En cas d’utilisation de ActionCable/Turbo Streams, il faut configurer
SolidCableavec une connexion DB distincte
Scalabilité et performances
- SolidQueue est suffisamment scalable pour la plupart des applications Rails
- Avec PostgreSQL, il peut traiter 200 à 300 tâches par seconde, et 37signals traite 20 millions de tâches par jour sans Redis
- Tableau comparatif
Élément Redis + Sidekiq SolidQueue Complexité de configuration Service séparé nécessaire Utilise la DB intégrée Langage de requête Commandes Redis SQL Monitoring Tableau de bord séparé Mission Control Scénarios de panne 6 ou plus 2 Débit Plusieurs milliers/s 200–300/s Cas adaptés 99,9 % des apps 95 % des apps
Conclusion
- Redis et Sidekiq sont d’excellentes technologies, mais elles entraînent une complexité et un coût excessifs pour la plupart des applications Rails
- SolidQueue permet, avec une base de données unique, de simplifier l’exploitation, réduire les coûts et améliorer la maintenance
- À l’ère de Rails 8, il est recommandé d’adopter SolidQueue comme choix par défaut
2 commentaires
Redis, c’est bien.
Avis Hacker News
Je pense que tous les auteurs open source ont le droit de contrôler le périmètre de leur projet
Mais notre équipe regrette d’être passée de good_job à SolidQueue
Basecamp est centré sur MySQL, donc ils n’acceptent pas les requêtes spécifiques au moteur RDBMS. En regardant les issues GitHub, on voit qu’ils se concentrent uniquement sur les performances de MySQL
De plus, il n’y a toujours pas de prise en charge des traitements par lot (PR liée)
Sur les JOIN complexes, MySQL construit souvent un mauvais plan d’exécution, donc j’impose l’ordre avec STRAIGHT_JOIN. C’est une précaution pour l’avenir
Je compare justement les deux comme candidats pour migrer depuis resque. GoodJob n’est pas compatible avec le mode transaction de pgbouncer à cause de ses fonctionnalités propres à pg
Le besoin de persistance de session est pénible, mais le gain de performances n’a pas beaucoup d’importance à la plupart des échelles
Malgré ça, le modèle de développement et la lisibilité du code de GoodJob inspirent bien davantage confiance
C’est toujours une bonne chose si l’environnement de production peut être simplifié
Dans Rails, je pense que la situation idéale est une architecture qui permet de basculer facilement vers Redis
Ce serait bien de pouvoir commencer avec SolidQueue puis migrer vers Redis si on finit par atteindre des limites de scalabilité
La plupart des applications Rails n’ont pas un trafic énorme, donc maintenir les deux systèmes ajoute plutôt de la complexité
Bien sûr, certaines applications dépendent d’une implémentation de file précise, mais dans le cas général il suffit de changer la configuration
J’aimerais savoir s’il combine aussi des snapshots pour éviter que le journal ne devienne trop gros, et si cela fonctionne aussi en mode distribué
En particulier quand la création des jobs se produit en même temps que d’autres changements en base, perdre cette garantie pose problème
Redis avait ici l’avantage d’être un stockage d’état léger et indépendant
SolidQueue ne semble pas clarifier cette séparation (riverqueue.com)
J’ai testé SolidQueue sur mon projet perso
Ma conclusion, c’est que s’il n’y a pas de problème avec Sidekiq, il n’y a pas de raison de changer
Ça ne vaut la peine d’être envisagé que si on veut supprimer l’infrastructure Redis
Pour un nouveau projet, GoodJob est plus mature et bénéficie d’une meilleure communauté
L’UI de SolidQueue est trop basique, ce qui m’a gêné. Les index n’étaient pas optimisés, et avec beaucoup de données la page se figeait
Il faut aussi prendre en compte le coût de gestion du pool de connexions supplémentaire quand on utilise un RDBMS
Pour ceux qui s’inquiètent de la scalabilité, si on regarde les benchmarks d’Oban en Elixir,
il traite un million de jobs par minute sur un seul nœud. La plupart des applications ont un volume bien inférieur
Il insère les 5000 jobs en une seule fois par lots, donc le TPS réel est d’environ 200
Sans batch, si on insère les jobs individuellement, la charge des transactions SQL augmente beaucoup
Avant SolidQueue, nous stockions déjà les jobs en base
L’avantage, c’est qu’on peut faire un snapshot de l’état de production tel quel vers l’environnement de développement
En revanche, nous gardons le rate limiter dans Redis, pour éviter de surcharger la base
La limite des files basées sur une base de données, c’est la taille importante des payloads
Mettre de gros JSON dans la file est inefficace à cause du surcoût d’écriture en base
Redis (Sidekiq) est bien plus rapide dans ce cas
SolidQueue + SQLite peut convenir si c’est simplement pour transmettre une clé primaire
Mais si plusieurs workers interrogent la même base en polling, on arrive vite à un goulot d’étranglement
Je pense qu’il vaut mieux mettre les grosses données dans un stockage externe comme S3 et ne transmettre qu’une référence
Je me demande s’il existe un document qui résume les résultats de benchmarks
SolidQueue mentionne SKIP LOCKED, mais garder une transaction ouverte pour un job de 15 minutes est risqué
Les transactions longues dégradent les performances de la base et sont vulnérables aux coupures réseau
Ce genre de structure peut mener à des anti-patterns. En regardant ensuite de plus près, cela semble fonctionner avec un système de lease
Je me reconnais dans la philosophie Postgres for everything
Je pense que c’est bien de tout unifier autour de PostgreSQL pour rester simple
Je ne sais pas vraiment comment répondre à cette analogie
Je me demande s’il y a encore une raison d’utiliser Redis au prix d’une complexité supplémentaire
« Une activité où une latence inférieure à 1 ms est importante » : on parle de faire du HFT avec Rails ?
Postgres va dévorer le monde