in Zero-Downtime-Deployments berücksichtigen
Der Symlink-Wechsel ist nicht das Ende eines Zero-Downtime-Deployments – er ist der Beginn einer kritischen Phase, in der Redis, RabbitMQ und OpenSearch mit dem neuen Code-Stand kompatibel sein müssen. Diese drei Dienste werden zu oft als Randdetails behandelt, obwohl sie häufig die Ursache von Post-Deploy-Fehlern sind.
Inhaltsverzeichnis
- 1. Warum diese drei Dienste gesondert betrachtet werden müssen
- 2. Redis in Magento: Cache, Sessions und FPC
- 3. Redis-Cache-Invalidierung im Deployment-Prozess
- 4. RabbitMQ: Queue-Consumer und Message-Persistenz
- 5. Queue-Consumer sicher pausieren und reaktivieren
- 6. OpenSearch: Index-Struktur und Mapping-Kompatibilität
- 7. Index-Updates im Zero-Downtime-Kontext
- 8. GitLab-Pipeline-Integration für alle drei Dienste
- 9. Dienste und ihre Deployment-Risiken im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Warum diese drei Dienste gesondert betrachtet werden müssen
Redis, RabbitMQ und OpenSearch sind keine einfachen Datenspeicher, die während eines Deployments ignoriert werden können. Sie halten Zustand, der spezifisch für eine bestimmte Code-Version ist: Redis-Cache-Einträge sind mit der Datenstruktur des alten Releases kodiert, RabbitMQ-Messages wurden von Consumer-Code produziert, der sich möglicherweise geändert hat, und OpenSearch-Indizes bilden eine Produktkatalog-Struktur ab, die neue Felder oder geänderte Mapping-Typen benötigt.
Das Problem tritt nicht bei einfachen Deployments auf, sondern bei den Deployments, bei denen sich die Datenstrukturen ändern. Ein neues Attribut in einem Produkt-Modell, ein geänderter Cache-Key-Format, ein neues Message-Format in einer Queue – diese Änderungen sind in der Code-Basis klar, aber ihre Auswirkungen auf laufende Dienste werden häufig nicht in den Deployment-Prozess einbezogen. Das Ergebnis: inkonsistente Zustände, die sich erst nach dem Symlink-Wechsel als Fehler manifestieren.
Der richtige Ansatz ist nicht, diese Dienste während des Deployments herunterzufahren – das würde Zero Downtime konterkarieren. Stattdessen geht es um präzises Timing: Redis-Flush erst nach dem Symlink-Wechsel, Queue-Consumer kurz pausieren während des kritischen Release-Wechsels, OpenSearch-Reindex als geplanter Nachfolgeschritt mit Alias-Swap. Diese Muster erlauben es, Zero Downtime zu erreichen und trotzdem eine saubere Zustandstransition sicherzustellen.
2. Redis in Magento: Cache, Sessions und FPC
Magento nutzt Redis typischerweise für drei separate Datenbanken: Cache (db 0), Full-Page-Cache (db 1) und Sessions (db 2). Diese Trennung ist wichtig für das Deployment, weil die drei Bereiche unterschiedliche Flush-Strategien benötigen. Der reguläre Cache enthält serialisierte PHP-Objekte und Konfigurationsdaten, die nach einem Code-Wechsel oft inkompatibel sind. Der Full-Page-Cache enthält fertig gerenderte HTML-Seiten, die nach einem Template-Change veraltet sind. Sessions enthalten Nutzer-Session-Daten, die nach einem Deployment meistens kompatibel bleiben, aber bei Änderungen an Session-Datenstrukturen geleert werden müssen.
Die häufigste Fehlerursache: Der Cache wird vor dem Symlink-Wechsel geleert, aber der neuen Code beginnt erst nach dem Wechsel, sodass das alte Release die Cache-Einträge mit der alten Struktur neu befüllt. Wenn dann der Symlink wechselt und der neue Code mit Einträgen der alten Struktur arbeiten muss, entstehen Deserialisierungsfehler. Die korrekte Sequenz: Cache leeren nach dem Symlink-Wechsel, nicht davor.
# Deploy job with correct Redis flush timing — after symlink switch
deploy:production:
stage: deploy
script:
- RELEASE_ID="$(date +%Y%m%d-%H%M%S)-${CI_COMMIT_SHORT_SHA}"
- RELEASE_PATH="${DEPLOY_PATH}/releases/${RELEASE_ID}"
# Step 1: Transfer artifact to new release directory
- rsync -az ./ "${DEPLOY_USER}@${DEPLOY_HOST}:${RELEASE_PATH}/"
# Step 2: Link shared files (env.php, media)
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}" "
ln -sfn ${DEPLOY_PATH}/shared/app/etc/env.php ${RELEASE_PATH}/app/etc/env.php &&
ln -sfn ${DEPLOY_PATH}/shared/pub/media ${RELEASE_PATH}/pub/media"
# Step 3: Run setup:upgrade in new release (before symlink!)
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}"
"cd ${RELEASE_PATH} && php bin/magento setup:upgrade --keep-generated"
# Step 4: Atomic symlink switch
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}"
"ln -sfn ${RELEASE_PATH} ${DEPLOY_PATH}/current"
# Step 5: Flush Redis AFTER symlink — new code now handles cache rebuilding
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}"
"cd ${DEPLOY_PATH}/current && php bin/magento cache:flush"
# Step 6: Verify Redis is still connected
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}"
"redis-cli -h ${REDIS_HOST} ping | grep -q PONG || exit 1"
3. Redis-Cache-Invalidierung im Deployment-Prozess
Die Strategie für Redis-Cache-Invalidierung hängt von der Art des Deployments ab. Bei reinen Code-Änderungen ohne Datenbankmigrationen ist ein vollständiger Cache-Flush nach dem Symlink-Wechsel ausreichend und sicher. Bei Deployments mit Datenbankmigrationen, neuen Konfigurationsoptionen oder geänderten Serialisierungsstrukturen muss der Cache vor dem Symlink-Wechsel geleert werden und darf zwischen dem alten und neuen Code kein veralteter Eintrag im Cache landen.
Ein häufig übersehenes Detail: bin/magento cache:flush und bin/magento cache:clean haben unterschiedliche Auswirkungen. cache:flush löscht alle Keys im konfigurierten Redis-Backend vollständig. cache:clean markiert nur Magento-spezifische Cache-Einträge als ungültig, lässt aber andere Backend-Daten unberührt. Für Deployments ist cache:flush die sicherere Wahl, weil es keine Annahmen darüber macht, welche Keys möglicherweise inkompatibel sind.
4. RabbitMQ: Queue-Consumer und Message-Persistenz
RabbitMQ in Magento verarbeitet asynchrone Operationen über Queue-Consumer: E-Mail-Versand, Indexer-Updates, Bestellverarbeitung und andere Background-Tasks. Diese Consumer laufen als separate Prozesse, die kontinuierlich Messages aus den Queues abholen. Das Problem beim Deployment: ein Consumer-Prozess, der mit dem alten Code läuft, verarbeitet Messages mit dem alten Consumer-Code, während der neue Code bereits aktiv ist. Je nach Art der Message kann das zu Inkompatibilitäten führen.
Die Situation ist besonders kritisch, wenn ein Deployment das Message-Format einer Queue ändert. Messages, die vom alten Code produziert und noch nicht verarbeitet wurden, haben das alte Format. Wenn der Consumer auf das neue Format aufgerüstet wird, kann er die alten Messages möglicherweise nicht korrekt deserialisieren. In den meisten Magento-Deployments ist das kein Problem, weil das Message-Format sich selten ändert – aber wenn es sich ändert, muss der Consumer-Prozess während des kritischen Zeitfensters pausiert werden.
5. Queue-Consumer sicher pausieren und reaktivieren
Das Pausieren und Reaktivieren von RabbitMQ-Consumer-Prozessen ist in Magento über Supervisor oder systemd realisierbar. Der sicherste Zeitpunkt für die Pause: unmittelbar vor dem Symlink-Wechsel. Die Consumer-Prozesse werden gestoppt, der Symlink-Wechsel findet statt, setup:upgrade und Cache-Flush laufen ab, dann werden die Consumer mit dem neuen Code wieder gestartet. Das Zeitfenster ist typischerweise unter 30 Sekunden, während dem Messages in der Queue akkumulieren, aber nicht verloren gehen.
Magento bietet ab Version 2.4 auch die Möglichkeit, Consumer mit einem PID-File zu verwalten. bin/magento queue:consumers:start ConsumerName --pid-file-path=/tmp/consumer.pid startet einen Consumer und speichert die PID. Das ermöglicht ein sauberes Stoppen über kill -SIGTERM $(cat /tmp/consumer.pid), das den Consumer wartet, bis die aktuelle Message verarbeitet ist, bevor er beendet wird. Dieses graceful shutdown verhindert, dass eine Message mitten in der Verarbeitung abgebrochen wird.
# Deployment with RabbitMQ consumer management and OpenSearch reindex
deploy:with-services:
stage: deploy
script:
- RELEASE_PATH="${DEPLOY_PATH}/releases/$(date +%Y%m%d-%H%M%S)"
# Step 1: Stop queue consumers gracefully before symlink switch
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}" "
supervisorctl stop magento-consumers:* 2>/dev/null || true &&
echo 'Waiting for consumers to finish current messages...' &&
sleep 5"
# Step 2: Transfer artifact and link shared files
- rsync -az ./ "${DEPLOY_USER}@${DEPLOY_HOST}:${RELEASE_PATH}/"
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}" "
ln -sfn ${DEPLOY_PATH}/shared/app/etc/env.php ${RELEASE_PATH}/app/etc/env.php &&
ln -sfn ${DEPLOY_PATH}/shared/pub/media ${RELEASE_PATH}/pub/media"
# Step 3: Run setup:upgrade in new release
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}"
"cd ${RELEASE_PATH} && php bin/magento setup:upgrade --keep-generated"
# Step 4: Atomic symlink switch
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}"
"ln -sfn ${RELEASE_PATH} ${DEPLOY_PATH}/current"
# Step 5: Flush Redis cache with new code active
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}"
"cd ${DEPLOY_PATH}/current && php bin/magento cache:flush"
# Step 6: Restart consumers with new code
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}"
"supervisorctl start magento-consumers:* 2>/dev/null || true"
# Step 7: Trigger OpenSearch reindex asynchronously (non-blocking)
- ssh "${DEPLOY_USER}@${DEPLOY_HOST}" "
cd ${DEPLOY_PATH}/current &&
nohup php bin/magento indexer:reindex catalogsearch_fulltext \
> ${DEPLOY_PATH}/shared/var/log/reindex.log 2>&1 &
echo 'OpenSearch reindex started in background'"
6. OpenSearch: Index-Struktur und Mapping-Kompatibilität
OpenSearch in Magento hält den Produktkatalog in einem Index mit einem definierten Mapping. Wenn ein Deployment neue Produktattribute hinzufügt, bestehende Attribute ändert oder das Mapping-Schema modifiziert, muss der Index aktualisiert werden. Das Problem: ein vollständiger Reindex für einen großen Katalog dauert Minuten bis Stunden. Während des Reindexes sind Suchergebnisse möglicherweise unvollständig oder inkorrekt.
Die professionelle Lösung für Zero-Downtime-Index-Updates ist das Alias-Swap-Pattern: Ein neuer Index wird im Hintergrund aufgebaut (z.B. magento_catalog_product_v2), während der aktive Alias magento_catalog_product noch auf den alten Index zeigt. Erst wenn der neue Index vollständig aufgebaut ist, wird der Alias auf den neuen Index umgeschwenkt. Der Wechsel ist atomar und für die Anwendung unsichtbar. Magento unterstützt dieses Muster nativ ab Version 2.4.6 über den OpenSearch-Adapter.
7. Index-Updates im Zero-Downtime-Kontext
Für Deployments ohne Mapping-Änderungen ist ein inkrementeller Reindex nach dem Deployment ausreichend. Magento markiert Produkte, die seit dem letzten vollständigen Index geändert wurden, als "require reindex" – ein inkrementeller Reindex arbeitet nur diese Produkte auf, nicht den gesamten Katalog. Dieser Prozess kann asynchron nach dem Deployment starten und blockiert weder den Symlink-Wechsel noch die Cache-Flush-Phase.
Für Deployments mit Mapping-Änderungen – also wenn neue Felder im Index erscheinen müssen – ist das Alias-Swap-Pattern erforderlich. In der GitLab-Pipeline bedeutet das einen zusätzlichen Job nach dem Deploy-Job, der den Reindex startet und entweder auf seinen Abschluss wartet oder asynchron läuft und über ein separates Monitoring überwacht wird. Der Verify-Job sollte in diesem Fall einen Check enthalten, der bestätigt, dass die Suche auf der Website korrekte Ergebnisse liefert.
8. GitLab-Pipeline-Integration für alle drei Dienste
Die Integration von Redis, RabbitMQ und OpenSearch in die GitLab-Pipeline erfolgt über dedizierte Schritte im Deploy-Job, nicht über separate Jobs. Der Grund: die Reihenfolge der Schritte ist kritisch und muss atomar durchgeführt werden. Ein separater Job hätte eine Lücke zwischen dem Ende des Deploy-Jobs und dem Beginn des Service-Management-Jobs, in der die Consumer mit dem falschen Code-Stand laufen könnten.
Die Verify-Stage sollte alle drei Dienste explizit prüfen: Redis-Erreichbarkeit über redis-cli ping, Queue-Consumer-Status über supervisorctl status oder bin/magento queue:consumers:list, und OpenSearch-Erreichbarkeit über einen einfachen HTTP-Check auf den Cluster-Endpoint. Diese Checks kosten zusammen unter 10 Sekunden und geben einem Team das nötige Vertrauen, dass alle Dienste nach dem Deployment korrekt funktionieren.
9. Dienste und ihre Deployment-Risiken im Vergleich
Die drei Dienste haben unterschiedliche Risikoprofile beim Deployment. Redis ist am häufigsten betroffen, weil Magento alle kritischen Cache-Strukturen in Redis hält. RabbitMQ ist selten kritisch, außer wenn Message-Formate sich ändern. OpenSearch-Reindex-Verzögerungen sind die häufigste Ursache von "Suche zeigt veraltete Daten"-Meldungen nach Deployments.
| Dienst | Hauptrisiko | Deployment-Aktion | Timing |
|---|---|---|---|
| Redis (Cache) | Inkompatible serialisierte Objekte | cache:flush | Nach Symlink-Wechsel |
| Redis (FPC) | Veraltete HTML-Seiten | cache:flush (FPC) | Nach Symlink-Wechsel |
| RabbitMQ | Consumer läuft mit altem Code | Stop/Start Consumers | Vor/Nach Symlink |
| OpenSearch | Veraltete oder inkompatible Indizes | Async Reindex | Nach Deployment |
| Redis (Sessions) | Inkompatible Session-Struktur | Flush nur bei Strukturänderung | Vor Symlink (selten) |
Die Tabelle zeigt, dass die meisten Deployment-Aktionen für diese Dienste nach dem Symlink-Wechsel stattfinden – mit Ausnahme der Queue-Consumer-Pause, die kurz vor dem Wechsel beginnt. Diese Sequenz ist nicht zufällig: sie stellt sicher, dass der neue Code als erstes mit dem neuen Systemzustand arbeitet, ohne dass der alte Code die Datenstrukturen mit inkompatiblen Daten befüllt hat.
10. Zusammenfassung
Redis, RabbitMQ und OpenSearch sind keine passiven Dienste, die ein Deployment unbeschadet überstehen. Sie halten versionsspezifischen Zustand, der nach einem Code-Wechsel explizit behandelt werden muss. Die Kernprinzipien: Redis-Cache nach dem Symlink-Wechsel leeren, Queue-Consumer kurz pausieren und mit neuem Code-Stand neu starten, OpenSearch-Reindex asynchron nach dem Deployment anstoßen und in der Verify-Stage alle drei Dienste auf Erreichbarkeit und korrekten Zustand prüfen.
Die gute Nachricht: diese Schritte lassen sich vollständig in eine GitLab-Pipeline integrieren, ohne Downtime zu erzeugen. Das kritische Zeitfenster – von Consumer-Pause bis Cache-Flush – dauert unter 30 Sekunden. In diesem Fenster akkumulieren Messages in der Queue und Nutzer bekommen möglicherweise noch gecachte Seiten ausgeliefert, aber die Anwendung ist nicht ausgefallen. Das ist der praktische Inhalt von Zero Downtime: keine Ausfälle, aber ein kurzes Fenster mit kontrollierten Einschränkungen.
Redis, RabbitMQ und OpenSearch im Deployment — Das Wichtigste auf einen Blick
Redis-Flush-Timing
cache:flush nach dem Symlink-Wechsel ausführen, nicht davor. Neuer Code befüllt den Cache mit kompatiblen Strukturen.
Queue-Consumer
Graceful Stop vor dem Symlink-Wechsel, Restart danach. Maximales Pause-Fenster: 30 Sekunden. Messages akkumulieren, gehen nicht verloren.
OpenSearch-Reindex
Asynchron nach dem Deployment starten. Für Mapping-Änderungen: Alias-Swap-Pattern nutzen. Verify-Job prüft Suche nach dem Deployment.
Verify-Stage
Redis-Ping, Consumer-Status-Check und OpenSearch-HTTP-Check als Teil der Verify-Stage nach jedem Deployment mit diesen Diensten.