Wie Songkick seine Infrastruktur mit Memorystore vereinheitlicht
Paul Lawson
Principal Architect, Songkick
Wir von Songkick, als Teil der Warner Music Group, bieten unseren Nutzer:innen eine Suchfunktion für Konzerte und darüber hinaus eine Livemusik-Plattform, um Musikfans an Live-Events teilhaben zu lassen. Jährlich ermöglichen wir über 175 Millionen Musikfans aus aller Welt, ihren Lieblingskünstler:innen zu folgen, nach Konzerten und Livestreams zu suchen sowie auf sichere Weise über mobile Apps und online über eine Website Tickets zu buchen.
Wir beschäftigen in London etwa 15 Entwickler:innen in vier Teams. Meine Aufgabe ist es, diese Teams bei ihren technischen Entscheidungen und bei der Entwicklung von Lösungen zu unterstützen. Nach der Migration zu Google Cloud waren wir auf der Suche nach einer komplett verwalteten Caching-Lösung. Diese sollte sich nahtlos in die anderen von uns geschätzten Google-Tools einbinden lassen und unseren Entwickler:innen die Möglichkeit geben, innovative Produkte zu erstellen, die unsere Kund:innen begeistern. Memorystore, der skalierbare, sichere und hochverfügbare Speicherdienst von Google für Redis, war hierfür die richtige Lösung.
Mehr Zeit für Innovation dank des komplett verwalteten Memorystore-Dienstes
Unsere ursprüngliche Caching-Infrastruktur basierte ausschließlich auf lokalem Memcached, eine für uns damals einfach anwendbare Lösung. Schließlich haben wir auf Redis umgestellt, da wir dessen fortgeschrittene Features wie Wörterbücher und Zählerfunktionen nutzen wollten. In unserer dienstorientierten Architektur waren beide Open-Source-Datenspeicher im Einsatz. Wir hatten zwei Redis-Cluster: einen für nichtflüchtige Daten und einen anderen als einfache Caching-Ebene zwischen unserer Front-End-Anwendung und unseren Diensten.
Bei unseren Diskussionen über die Nutzung von Google Cloud wurde deutlich, dass die gleichzeitige Anwendung von zwei Caching-Technologien (Memcached und Redis) keinen echten Vorteil bietet. Wir haben uns dann ausschließlich für Redis entscheiden, da damit alle unsere Anwendungsfälle abgedeckt werden und wir so kein Know-how für zwei Datenbanken benötigen. Uns ist bewusst, dass Redis in der Anwendung und Verwaltung komplexer sein kann. Das ist für uns aber kein großes Problem, denn der von uns genutzte Memorystore wird komplett von Google Cloud verwaltet. Da durch Memorystore komplexe Redis-Aufgaben automatisiert werden, beispielsweise die Aktivierung von Hochverfügbarkeit, Failover, Patching und Monitoring, steht uns nun mehr Zeit für die Entwicklung innovativer Funktionen und Produkte zur Verfügung.
So fallen z. B. die Stunden weg, in denen wir bisher beschädigte Redis-Cluster und Netzwerkprobleme beheben mussten. Unser Team hat viel Erfahrung in der Entwicklung, aber weniger in der Verwaltung der Infrastruktur. Die Probleme mit Redis wurden deshalb für unser Team zum Störfaktor und kosteten Zeit. Darüber hinaus besteht bei einem selbstverwalteten Tool immer die Gefahr, dass es zu Ausfallzeiten für die Nutzer:innen kommt. Memorystore stellt dagegen eine sichere, komplett verwaltete Option dar, die kostengünstig ist und eine Lösung dieser Probleme bietet. Damit lassen sich die Vorteile von Redis ohne aufwendige Verwaltung nutzen. Die Entscheidung dafür fiel uns deshalb nicht schwer.
Wie wir Memorystore nutzen
Wenden wir uns nun einigen unserer Anwendungsfälle für Memorystore zu. Es gibt zwei Caching-Ebenen bei Memorystore: Die Front-End-Anwendung führt ein Caching der Ergebnisse von API-Aufrufen für unsere Dienste durch, andere Dienste erledigen das Caching der Datenbankergebnisse. In der Regel besteht unser Caching-Schlüssel für die Front-End-Dienste aus der URL und allen primitiven Werten, die übergeben werden. Anhand der URL und der Abfrageparameter prüft die Front-End-Anwendung, ob bereits Daten vorhanden sind oder ob sie mit dem Dienst Kontakt aufnehmen muss.
Einige unserer Dienste enthalten sogar eine eigene Caching-Ebene, die zuerst mit Redis kommuniziert und dann gegebenenfalls unsere Geschäftslogik abruft und eine Verbindung zu den Datenbanken herstellt. Dieses Caching sitzt vor dem Dienst und arbeitet nach den gleichen Regeln wie das Front-End-Caching.
Außerdem nutzen wir Fastly als Caching-Ebene vor unseren Front-Ends. Auf Seitenebene wird damit gegebenenfalls die gesamte Seite umfassend in Fastly zwischengespeichert, z. B. wenn eine Seite eine Bestenliste der Top-Künstler:innen auf der Plattform enthält.
Memorystore wird dann für Inhalte auf der Ebene der Benutzer:innen verwendet, etwa wenn eine Veranstaltungsseite Informationen über die Künstlerin oder den Künstler und/oder die Veranstaltung sowie Empfehlungen für Künstler:innen abruft. Falls der Fastly-Cache auf der Unterseite der Künstlerin oder des Künstlers abgelaufen ist, wird er an die Front-End-Anwendung übergeben, die dann die verschiedenen Dienste kontaktiert, um alle angeforderten Informationen auf der Seite zur Verfügung zu stellen. In diesem Fall können drei verschiedene Datenelemente in unserem Redis-Cache enthalten sein. Die Unterseiten der Künstler:innen enthalten außerdem Komponenten, die nicht in Fastly zwischengespeichert werden. Deshalb greifen wir sehr viel mehr auf Redis zurück.
Die Gültigkeitsdauer (Time-to-live, TTL) unseres Redis-Cache ist in der Regel recht kurz. Manchmal sind Einträge nur für 10 Minuten verfügbar. Bei sehr statischen Daten können diese dagegen für einige Stunden in Redis zwischengespeichert sein. Wir bestimmen für jedes Datenelement einen sinnvollen Caching-Zeitraum und legen dann auf dieser Grundlage die Gültigkeitsdauer fest. Angenommen, eine bestimmte Künstlerin oder ein bestimmter Künstler wird 100.000-mal am Tag aufgerufen. Schon ein 10-minütiger Cache hat dann einen großen Einfluss darauf, wie viele Aufrufe täglich an unseren Dienst übergeben werden müssen.
Für einen solchen Anwendungsfall haben wir einen hochverfügbaren Memorystore-Cluster von ca. 4 GB Arbeitsspeicher eingerichtet und nutzen eine Richtlinie zur Cache-Entleerung von allkeys-lru (zuletzt verwendete Schlüssel). Für diesen Cluster erhalten wir im Moment etwa 400 Anfragen pro Sekunde zu Spitzenzeiten. Dies ist das durchschnittliche tägliche Anfragevolumen, das unter bestimmten Bedingungen aber noch sehr viel höher ausfallen kann.
In unserer alten Infrastruktur hatten wir zwei verschiedene Redis-Cluster. Der erste Cluster entsprach dem gerade beschriebenen. Der zweite Cluster war ein nichtflüchtiger Redis-Cluster. Im Zuge der Migration zu Google Cloud haben wir dann beschlossen, Redis möglichst optimal zu nutzen. Dafür haben wir die vier oder fünf Features vereinfacht und neu konzipiert, die den nichtflüchtigen Redis-Speicher verwenden, entweder mithilfe von Cloud SQL for MySQL oder mit BigQuery. Manchmal nutzen wir Redis auch zum Aggregieren von Daten. In Google Cloud können wir dafür jetzt einfach BigQuery verwenden und haben so sehr viel bessere Analysemöglichkeiten als beim Aggregieren mit Redis.
Wir verwenden Memorystore auch für einen verteilten wechselseitigen Ausschluss. Bei bestimmten Aktionen in unserem System sollen einige Vorgänge nicht gleichzeitig ausgeführt werden. Dies gilt beispielsweise für die Migration von Daten für eine spezielle Veranstaltung, bei der zwei Administrator:innen zur gleichen Zeit versuchen, dieselbe Aufgabe durchzuführen. Wenn diese Datenmigration gleichzeitig ausgeführt wird, kann es zu Fehlern in unserem System kommen. Deshalb nutzen wir in solchen Fällen Redis als Sperre in Form eines wechselseitigen Ausschlusses zwischen verschiedenen Prozessen, um zu gewährleisten, dass sie nacheinander und nicht gleichzeitig ausgeführt werden.
Problemlose Zusammenarbeit von Memorystore und Redis
Seit der Migration sind keine Probleme mit Redis aufgetreten. Außerdem schätzen wir die Monitoring-Funktionen, die mit Memorystore einsatzfertig zur Verfügung stehen. Nach der Bereitstellung eines neuen Features können wir im Handumdrehen feststellen, ob es sofort Daten an den Cache übergibt oder ob die Trefferquote sehr niedrig ist. Letzteres weist darauf hin, dass die Implementierung fehlerhaft ist.
Ein weiterer Vorteil besteht darin, dass die Schnittstelle von Memorystore genau wie die von Redis funktioniert. Wir nutzen das herkömmliche Redis in einem Docker-Container in unseren Entwicklungsumgebungen. Wenn wir es dann lokal ausführen, können wir sofort feststellen, ob der Caching-Code exakt wie beabsichtigt funktioniert.
Wir arbeiten mit einer Produktions- und mit einer Staging-Umgebung. Beide Umgebungen werden als Virtual Private Clouds mit einem jeweils eigenen Memorystore-Cluster ausgeführt. Wir verwenden außerdem Unittests, die keinen direkten Einfluss auf die Redis-Nutzung haben, und Integrationstests, die sowohl mit lokalem MySQL in Docker als auch mit einem Redis-Speicher in Docker kommunizieren. Außerdem führen wir Akzeptanztests aus. Das sind Tests zur Browserautomatisierung in der Staging-Umgebung, die mit Cloud SQL und Memorystore kommunizieren.
Planung weiterer Schritte mit Memorystore
Für potenzielle zukünftige Anwendungsfälle von Memorystore werden wir ziemlich sicher unsere Infrastruktur mit Pub/Sub ergänzen. Außerdem werden wir Redis zum Deduplizieren von Nachrichten aus Pub/Sub nutzen, etwa damit eine E-Mail nicht kurz nacheinander mehrmals gesendet wird. Wir freuen uns auch schon auf die komplett verwalteten Pub/Sub-Dienste. Aktuell arbeiten wir mit RabbitMQ, für das aber zu oft ein Debugging notwendig ist. Wir haben Pub/Sub bereits probeweise für denselben Anwendungsfall genutzt. Da dies hervorragend funktioniert hat, lag auch dafür die Entscheidung auf der Hand.
Memorystore ist nur eine der Daten-Cloud-Lösungen von Google, die wir täglich nutzen. Dazu kommen noch Cloud SQL, BigQuery und Dataflow für ETL-Pipelines, Data-Warehouse-Prozesse und unsere Analyseprodukte. Damit aggregieren wir für Künstler:innen relevante Daten, führen diese nach MySQL zurück und stellen sie anschließend in unseren Produkten für Künstler:innen bereit. Wenn wir dann Pub/Sub einsetzen, nutzen wir im Prinzip jede Option des Google Cloud-Datenbanktyps. Das zeigt auch, wie zufrieden wir mit den Tools von Google Cloud sind.
Weitere Informationen zu unseren Musikdiensten und -produkten finden Sie auf der Songkick-Website. Möchten Sie mehr über Memorystore erfahren? Informieren Sie sich über Best Practices zur Leistungsoptimierung für Memorystore for Redis in unserem Blogartikel.