CI/CD
.yml
GitLab · Redis · RabbitMQ · OpenSearch · Zero Downtime
Redis, RabbitMQ und OpenSearch
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.

13 Min. Lesezeit Redis · cache:flush · RabbitMQ · OpenSearch · Index-Kompatibilität GitLab 16+ · Magento 2.4 · PHP 8.4

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.

11. FAQ: Redis, RabbitMQ und OpenSearch im Deployment

1Warum sollte Redis-Cache nach dem Symlink-Wechsel geleert werden?
Vor dem Wechsel befüllt der alte Code den Cache wieder mit inkompatiblen Einträgen. Nach dem Wechsel befüllt der neue Code ihn mit kompatiblen Strukturen – das ist die sichere Sequenz.
2Was ist der Unterschied zwischen cache:flush und cache:clean?
cache:flush löscht alle Keys vollständig. cache:clean markiert nur Magento-Einträge als ungültig. Für Deployments ist cache:flush sicherer.
3Gehen Messages in RabbitMQ verloren, wenn Consumer pausiert werden?
Nein. RabbitMQ ist ein persistenter Broker. Messages akkumulieren in der Queue und werden nach dem Consumer-Neustart verarbeitet.
4Wie lange sollte das Consumer-Pause-Fenster maximal dauern?
Idealerweise unter 30 Sekunden. Consumer stoppen → Symlink wechseln → setup:upgrade → cache:flush → Consumer starten. Länger deutet auf ein Problem im Prozess hin.
5Was ist das Alias-Swap-Pattern für OpenSearch?
Neuer Index im Hintergrund aufbauen, dann Alias atomar auf den neuen Index umzeigen. Für die Anwendung unsichtbar – keine Suchergebnisunterbrechung.
6Muss der OpenSearch-Index bei jedem Deployment neu aufgebaut werden?
Nein, nur bei Mapping-Änderungen. Bei reinen Code-Deployments reicht ein inkrementeller Reindex der geänderten Produkte.
7Wie prüfe ich in der Verify-Stage, ob die Suche funktioniert?
Mit curl auf eine Suchanfrage: curl -f 'https://shop.example.com/catalogsearch/result/?q=test'. HTTP 200 bestätigt Erreichbarkeit. OpenSearch-Cluster-Health für tiefere Prüfung.
8Können Redis-Session-Daten bei einem Deployment verloren gehen?
Bei normalem Deployment ohne Session-Struktur-Änderung nein. Sessions bleiben erhalten. Nur bei Änderungen der Session-Datenstruktur müssen Sessions geleert werden.
9Wie erkenne ich, dass ein Consumer mit dem falschen Code-Stand läuft?
Über supervisorctl status oder den Prozess-Startzeitpunkt. Ein Consumer der vor dem Symlink-Wechsel gestartet wurde und nicht neu gestartet wurde, läuft mit dem alten Code.
10Was passiert, wenn Redis während des Deployments nicht erreichbar ist?
Magento fällt auf dateibasiertes Caching zurück – erhebliche Performance-Einbußen. Der Verify-Job sollte redis-cli ping prüfen und bei fehlendem PONG fehlschlagen.