Wie haben wir den starken Anstieg der x10-Last auf dem Remote-Standort überstanden und welche Schlussfolgerungen haben wir gezogen?

Hallo Habr! In den letzten Monaten haben wir in einer sehr interessanten Situation gelebt, und ich möchte unsere Geschichte der Infrastrukturskalierung teilen. In dieser Zeit wuchs der Auftragseingang von SberMarket um das Vierfache und startete einen Service in 17 neuen Städten. Aufgrund des explosionsartigen Anstiegs der Nachfrage nach Lebensmittellieferungen mussten wir unsere Infrastruktur skalieren. Lesen Sie die interessantesten und nützlichsten Ergebnisse unter der Katze.



Mein Name ist Dima Bobylev, ich bin der technische Direktor von SberMarket. Da dies der erste Beitrag in unserem Blog ist, sage ich ein paar Worte über mich und das Unternehmen. Im vergangenen Herbst nahm ich am Wettbewerb der jungen Anführer der Runet teil. Für den Wettbewerb habe ich eine kurze Geschichte darüber geschrieben, wie wir bei SberMarket die interne Kultur und Herangehensweise an die Entwicklung des Dienstes sehen. Und obwohl es nicht möglich war, den Wettbewerb zu gewinnen, habe ich mir die Grundprinzipien für die Entwicklung des IT-Ökosystems formuliert.

Bei der Leitung eines Teams ist es wichtig, die Anforderungen des Unternehmens und die Anforderungen der einzelnen Entwickler zu verstehen und in Einklang zu bringen. Jetzt wächst SberMarket 13 Mal von Jahr zu Jahr. Dies wirkt sich auf das Produkt aus und erfordert eine konstante Steigerung des Volumens und des Entwicklungstempos. Trotzdem widmen wir den Entwicklern genügend Zeit für vorläufige Analysen und qualitativ hochwertiges Schreiben von Code. Der gebildete Ansatz hilft nicht nur bei der Schaffung eines funktionierenden Produkts, sondern auch bei seiner weiteren Skalierung und Entwicklung. Infolge dieses Wachstums hat sich SberMarket bereits zu einem führenden Anbieter von Lieferservices für Lebensmittel entwickelt: Wir liefern täglich etwa 18.000 Bestellungen, obwohl es Anfang Februar etwa 3.500 Bestellungen gab.


Einmal bat ein Kunde den SberMarket-Kurier, ihm Produkte kontaktlos zu liefern - direkt auf den Balkon

Aber gehen wir weiter zu den Einzelheiten. In den letzten Monaten haben wir die Infrastruktur unseres Unternehmens aktiv skaliert. Ein solcher Bedarf wurde durch externe und interne Faktoren erklärt. Gleichzeitig mit der Erweiterung des Kundenstamms stieg die Anzahl der verbundenen Filialen von 90 zu Jahresbeginn auf über 200 bis Mitte Mai. Natürlich haben wir die Hauptinfrastruktur vorbereitet, reserviert und mit der Möglichkeit der vertikalen und horizontalen Skalierung aller virtuellen Maschinen in der Yandex-Cloud gerechnet. Die Praxis hat jedoch gezeigt: "Alles, was schief gehen kann, geht schief." Und heute möchte ich die interessantesten Situationen teilen, die in diesen Wochen passiert sind. Ich hoffe, unsere Erfahrung wird Ihnen nützlich sein.

Sklave in voller Alarmbereitschaft


Noch bevor die Pandemie begann, waren wir mit einer Zunahme der Anfragen an unsere Backend-Server konfrontiert. Die Tendenz, Produkte mit Lieferung nach Hause zu bestellen, gewann zunehmend an Bedeutung, und mit der Einführung der ersten Selbstisolierungsmaßnahmen im Zusammenhang mit COVID-19 stieg die Belastung den ganzen Tag vor unseren Augen dramatisch an. Die Master-Server der Hauptdatenbank mussten schnell entladen und ein Teil der Leseanforderungen an die Replikatserver (Slaves) übertragen werden.

Wir haben uns im Voraus auf diesen Schritt vorbereitet und für ein solches Manöver waren bereits 2 Slave-Server gestartet worden. Sie arbeiteten hauptsächlich an Batch-Aufgaben zur Generierung von Informations-Feeds für den Datenaustausch mit Partnern. Diese Prozesse verursachten eine zusätzliche Belastung und wurden zu Recht einige Monate zuvor „außerhalb der Klammern“ platziert. 

Da es auf Slave eine Replikation gab, haben wir uns an das Konzept gehalten, dass Anwendungen nur im schreibgeschützten Modus mit ihnen arbeiten können. Der Disaster Recovery Plan schlug vor, dass wir im Katastrophenfall einfach den Slave anstelle des Masters einbinden und alle Schreib- und Leseanforderungen an den Slave senden könnten. Wir wollten jedoch auch Replikate für die Anforderungen der Analyseabteilung verwenden, sodass die Server nicht vollständig in den Status "Nur Lesen" versetzt wurden und jeder Host seine eigenen Benutzer hatte und einige über Schreibberechtigungen zum Speichern von Zwischenberechnungsergebnissen verfügten.

Bis zu einer bestimmten Auslastung hatten wir genügend Assistenten zum Schreiben und Lesen bei der Verarbeitung von http-Anforderungen. Mitte März, als Sbermarket sich entschied, vollständig auf einen Remote-Standort umzusteigen, begannen wir mit einer mehrfachen Erhöhung des RPS. Immer mehr unserer Kunden gingen zur Selbstisolierung oder zur Arbeit von zu Hause aus, was sich in den Lastindikatoren widerspiegelte.

Die Leistung des „Masters“ reichte nicht mehr aus, sodass wir einige der schwersten Leseanforderungen für ein Replikat ertragen mussten. Um Anfragen zum Schreiben an den Master und zum Lesen an den Slave transparent zu senden, haben wir den Rubinstein „ Octopus". Wir haben einen speziellen Benutzer mit dem Postfix _readonly ohne Schreibberechtigung erstellt. Aufgrund eines Fehlers in der Konfiguration eines der Hosts ging ein Teil der Schreibanforderungen im Auftrag eines Benutzers mit den entsprechenden Rechten an den Slave-Server.

Das Problem manifestierte sich nicht sofort, weil Eine erhöhte Last erhöhte die Slave-Verzögerung. Dateninkonsistenz wurde am Morgen aufgedeckt, als die Slaves nach nächtlichen Importen den Master nicht „einholten“. Wir führten dies auf die hohe Belastung des Dienstes selbst und den Import zurück, der mit der Einführung neuer Geschäfte verbunden ist. Es war jedoch inakzeptabel, Informationen zu den vielen Stunden Verzögerung zu geben, und wir wechselten zu den zweiten Analyseprozessen , die der Slave verwendet hatte, weil er für lshie-Ressourcen verwendet hatte und keine Leseanforderungen geladen hatte (und wir haben uns erklärt, dass keine Replikationsverzögerung vorliegt).

Als wir die Gründe für das „Kriechen“ des Hauptsklaven herausfanden, schlug die Analyse aus demselben Grund bereits fehl. Trotz des Vorhandenseins von zwei zusätzlichen Servern, auf die wir die Last im Falle eines Master-Absturzes aufgrund eines unglücklichen Fehlers übertragen wollten, stellte sich heraus, dass in einem kritischen Moment keine vorhanden sind.

Da wir jedoch nicht nur die Datenbank (der Rest betrug zu diesem Zeitpunkt etwa 5 Stunden), sondern auch einen Snapshot-Master-Server gesichert haben, konnten wir das Replikat innerhalb von 2 Stunden starten. Zwar wurde danach erwartet, dass wir das Replikationsprotokoll für eine lange Zeit rollen (da sich der Prozess im Single-Thread-Modus befindet, aber dies ist eine ganz andere Geschichte).

: , readonly . , .

« »


Obwohl wir den Katalog auf der Site ständig aktualisieren, erlaubten die Anfragen, die wir an die Slave-Server stellten, eine leichte Verzögerung vom Master. Die Zeit, in der wir das Problem des „plötzlichen Abbruchs von Sklaven“ entdeckten und beseitigten, war mehr als eine „psychologische Barriere“ (während dieser Zeit hätten die Preise aktualisiert werden können und die Kunden veraltete Daten gesehen hätten), und wir mussten alle Anfragen an den Hauptdatenbankserver umschalten . Infolgedessen funktionierte die Site langsam ... aber zumindest funktionierte sie. Und während sich der Sklave erholte, hatten wir keine andere Wahl, als zu optimieren. 

Während sich die Slave-Server erholten, zogen sich die Minuten langsam hin, der Master blieb überlastet, und wir haben alle Anstrengungen unternommen, um aktive Aufgaben gemäß der Pareto-Regel zu optimieren: Wir haben die TOP-Anforderungen ausgewählt, die den größten Teil der Last liefern, und mit der Optimierung begonnen. Dies geschah direkt "on the fly".

Ein interessanter Effekt war, dass MySQL, das in den Augapfel geladen wurde, sogar auf eine leichte Verbesserung der Prozesse reagiert. Die Optimierung eines Anforderungspaars, das nur 5% der Gesamtlast ergab, zeigte bereits eine spürbare CPU-Entladung. Infolgedessen konnten wir dem Master eine akzeptable Bereitstellung von Ressourcen zur Verfügung stellen, um mit der Datenbank zu arbeiten und die erforderliche Zeit für die Wiederherstellung von Replikaten zu erhalten. 

Fazit: Schon eine kleine Optimierung ermöglicht es Ihnen, bei Überlastung mehrere Stunden "zu überleben". Dies war gerade genug für uns bei der Wiederherstellung von Servern mit Replikaten. Übrigens werden wir die technische Seite der Abfrageoptimierung in einem der folgenden Beiträge diskutieren. Abonnieren Sie also unseren Blog, wenn dies für Sie nützlich sein könnte.

Organisieren Sie die Leistungsüberwachung von Partnerdiensten


Wir bearbeiten Bestellungen von Kunden und daher interagieren unsere Dienste ständig mit APIs von Drittanbietern - dies sind Gateways zum Senden von SMS, Zahlungsplattformen, Routing-Systemen, Geocoder, dem Federal Tax Service und vielen anderen Systemen. Und als die Last schnell zu wachsen begann, ruhten wir uns gegen die API-Einschränkungen unserer Servicepartner aus, an die wir vorher noch nicht einmal gedacht hatten.

Ein unerwarteter Überschuss an Quoten für Affiliate-Services kann zu eigenen Ausfallzeiten führen. Viele APIs blockieren Clients, die die Grenzwerte überschreiten, und in einigen Fällen kann ein Übermaß an Anforderungen die Produktion mit einem Partner überlasten. 

Zum Beispiel konnten zum Zeitpunkt der Erhöhung der Anzahl der Lieferungen die begleitenden Dienste die Aufgaben ihrer Verteilung und Bestimmung der Routen nicht bewältigen. Infolgedessen stellte sich heraus, dass die Bestellungen getätigt wurden und der Dienst, der die Route erstellt, nicht funktioniert. Ich muss sagen, dass unsere Logistiker es unter diesen Bedingungen fast unmöglich gemacht haben, und die klare Interaktion des Teams hat dazu beigetragen, vorübergehende Servicefehler auszugleichen. Es ist jedoch unmöglich, ein solches Volumen von Anträgen manuell manuell zu bearbeiten, und nach einiger Zeit würden wir eine inakzeptable Lücke zwischen Aufträgen und deren Ausführung feststellen. 

Eine Reihe von organisatorischen Maßnahmen wurden ergriffen, und die koordinierte Arbeit des Teams trug dazu bei, Zeit zu gewinnen, während wir uns auf neue Bedingungen einigten und auf die Modernisierung der Dienstleistungen einiger Partner warteten. Es gibt andere APIs, die Ihnen mit hoher Ausdauer und gottlosen Tarifen bei hohem Datenverkehr gefallen. Am Anfang haben wir beispielsweise eine bekannte Mapping-API verwendet, um die Adresse eines Zustellpunkts zu bestimmen. Aber am Ende des Monats erhielten sie eine ordentliche Rechnung von fast 2 Millionen Rubel. Danach beschlossen sie, es schnell zu ersetzen. Ich werde keine Werbung machen, aber ich werde sagen, dass unsere Ausgaben erheblich gesunken sind.

: . , « », , . , ,   . 

, « » ()


Wir sind es gewohnt, die Hauptdatenbank oder die Anwendungsserver anzuschließen, aber beim Skalieren können Probleme auftreten, die nicht erwartet wurden. Für die Volltextsuche auf der Site verwenden wir die Apache Solr-Engine. Mit zunehmender Auslastung stellten wir eine Verringerung der Antwortzeit fest und die Auslastung des Serverprozessors erreichte 100%. Was könnte einfacher sein - wir werden mit Solr mehr Ressourcen für den Container bereitstellen.

Anstelle des erwarteten Leistungsgewinns ist der Server einfach "gestorben". Es wurde sofort zu 100% geladen und reagierte noch langsamer. Anfangs hatten wir 2 Kerne und 2 GB RAM. Wir haben uns für das entschieden, was normalerweise hilft - wir haben dem Server 8 Kerne und 32 GB gegeben. Alles ist viel schlimmer geworden (genau wie und warum - wir werden es in einem separaten Beitrag erzählen). 

Mehrere Tage lang haben wir die Feinheiten dieses Problems herausgefunden und mit 8 Kernen und 32 GB eine optimale Leistung erzielt. Diese Konfiguration ermöglicht es uns, die Last heute weiter zu erhöhen, was sehr wichtig ist, da das Wachstum nicht nur in Bezug auf die Kunden, sondern auch in Bezug auf die Anzahl der verbundenen Geschäfte erfolgt - über 2 Monate hat sich ihre Anzahl verdoppelt. 

Schlussfolgerung: Standardmethoden wie "mehr Eisen hinzufügen" funktionieren nicht immer. Wenn Sie also einen Dienst skalieren, müssen Sie genau wissen, wie er Ressourcen verwendet, und seinen Betrieb unter neuen Bedingungen vorab testen. 

Staatenlos - der Schlüssel zur einfachen horizontalen Skalierung


Im Allgemeinen folgt unser Team einem bekannten Ansatz: Services sollten keinen zustandslosen Status haben und unabhängig von der Laufzeitumgebung sein. Dies ermöglichte es uns, das Lastwachstum durch einfache horizontale Skalierung zu überstehen. Wir hatten jedoch eine Service-Ausnahme - einen Handler für lange Hintergrundaufgaben. Er war damit beschäftigt, E-Mails und SMS zu senden, Ereignisse zu verarbeiten, Feeds zu generieren, Preise und Lagerbestände zu importieren und Bilder zu verarbeiten. Es kam vor, dass es vom lokalen Dateispeicher abhing und sich in einer einzigen Kopie befand. 

Wenn die Anzahl der Aufgaben in der Prozessorwarteschlange zunahm (und dies geschah natürlich mit einer Zunahme der Anzahl der Bestellungen), wurde die Leistung des Hosts, auf dem sich der Prozessor und der Dateispeicher befinden, zu einem begrenzenden Faktor. Infolgedessen wurden die Aktualisierung des Sortiments und der Preise, das Senden von Benachrichtigungen an Benutzer und viele andere wichtige Funktionen in der Warteschlange gestoppt. Das Ops-Team migrierte den Dateispeicher schnell in einen S3-ähnlichen Netzwerkspeicher. Dadurch konnten wir mehrere leistungsstarke Computer für die Skalierung des Hintergrund-Task-Handlers einrichten.

Schlussfolgerung: Die staatenlose Regel muss ausnahmslos für alle Komponenten eingehalten werden, auch wenn es den Anschein hat, dass wir uns definitiv nicht darum kümmern. Es ist besser, ein wenig Zeit mit der korrekten Organisation der Arbeit aller Systeme zu verbringen, als den Code in Eile neu zu schreiben und den überlasteten Dienst zu reparieren.

7 Prinzipien für intensives Wachstum


Trotz der Verfügbarkeit zusätzlicher Kapazitäten sind wir im Wachstumsprozess auf einige Rechen getreten. In dieser Zeit hat sich die Anzahl der Bestellungen um mehr als das Vierfache erhöht. Jetzt liefern wir bereits mehr als 17.000 Bestellungen pro Tag in 62 Städten und planen, unsere Geografie noch weiter auszubauen. Im ersten Halbjahr 2020 wird der Service voraussichtlich in ganz Russland eingeführt. Um der wachsenden Belastung gerecht zu werden, haben wir unter Berücksichtigung der bereits vollen Unebenheiten 7 Grundprinzipien der Arbeit unter Bedingungen konstanten Wachstums für uns entwickelt:

  1. -. Jira,   . . — . , , , , .
  2. . « » . , , . , .
  3. . -, . -, , .
  4. stateless. , . . , , S3. https://12factor.net. , .
  5. . , . , , - . , . 
  6. . , . , SMS . , .
  7. . , . , , . API, -. .


Nicht ohne Verluste, aber wir haben diese Phase überstanden, und heute versuchen wir, alle gefundenen Prinzipien einzuhalten, und jede Maschine kann die x4-Leistung leicht steigern, um Überraschungen zu bewältigen. 

In den folgenden Beiträgen werden wir unsere Erfahrungen bei der Untersuchung der Leistungssenkung in Apache Solr teilen sowie über die Optimierung von Abfragen und darüber sprechen, wie die Interaktion mit dem Federal Tax Service dem Unternehmen hilft, Geld zu sparen. Abonnieren Sie unseren Blog, damit Sie nichts verpassen, und teilen Sie uns in den Kommentaren mit, ob Sie während des wachsenden Verkehrs solche Probleme hatten.


All Articles