Managing Tech

Managing Technology, from the trenches

Infos

Im privaten Blog von Jan Miczaika geht es um die Arbeit mit Technologien, in Teams, und das insbesondere im Startup-Umfeld. Kontakt?
    jan -at- hitflip.de oder bei XING

Fast jeder, der Web-Anwendungen baut, stellt schnell fest dass es teuer und kompliziert ist Datenbanken zu skalieren. Webserver sind einfach. Storage ist halbwegs einfach. Datenbanken sind schwierig.

Im Rahmen des Hitmeister-Wachstums habe ich mich recht intensiv mit dem Thema beschäftigt.
Ich möchte in dieser kleinen Serie verschiedene Themen durchsprechen, die bei der Verteilung von Datenbanken immer wieder aufkommen. Heute Teil 1: die Verteilung von Lese- und Schreibzugriffen.

Der erste Schritt bei der Skalierung von mySQL, wenn man von 1 auf 2…n Server geht, ist die Lese- von den Schreibzugriffen zu trennen. Das geht auf 2 Arten:

  • Ein Proxy, wie MySQL Proxy oder Continuent/Sequoia
  • In der Applikation selbst.

Die Proxies

Continuent bietet eine Art Proxy an. Die Lesezugriffe werden auf n Server verteilt, Schreibzugriffe gehen auf alle. Das System bietet eine Reihe von management Tools dazu. Die (für mich disqualifizierende) Schwäche wird sichtbar: der langsamste Server im Cluster determiniert die Geschwindigkeit des Gesamtsystems. Continuent ist für hot fail-over Geschichten ganz gut, bei der Skalierung hilft es nicht. Das Gesamtsystem schafft wohl auch nur ca. 6-7K Queries pro Sekunde. Alexander Windbichler hat von ähnlichen Erfahrungen berichtet.

MySQL Proxy ist ein Projekt von Jan Kneschke (berühmt für seinen exzellenten Lighttpd). Mit der Programmiersprache LUA kann man MySQL Proxy diverse Tricks beibringen, u.a.das Verteilen von reads und writes auf verschiedene Server. Wir mussten MySQL Proxy jedoch leider verwerfen. Das Problem sieht man im folgenden Diagramm recht schnell (aus einem Post über MySQL Proxy geliehen, danke!):

Sobald man einen minimalen Replikationslag hat, sind die Antworten nicht mehr konsistent. Und einen Lag hat man in MySQL sehr schnell zwischen Master und Slave, gerade wenn man schwere Queries hat. Das heisst man muss dann entweder Kommentare o.ä. in die SQLs einbauen, um manche reads trotzdem auf den Master zu schicken, oder den Applikationscode so umschreiben, dass er mit inkonsistenten Antworten zurecht kommt. In unserer Applikation liefert jeder Add und Edit Service das Objekt zurück, was er gerade modifiziert hat. Da reichen wenige 100 ms Lag aus, und das ganze fliegt uns um die Ohren.

Die eigene Applikation umbauen

Am Ende haben wir uns dafür entschieden unseren eigenen read/write Handler zu schreiben. Unsere Entwickler können bei Queries entscheiden, ob diese auf „write“, „read“ oder „auto“ gehen. Write und Read erzwingen eine entsprechende Verbindung auf den jeweiligen Server. Auto lässt die API entscheiden: Ist die Query in einer Transaktion, landet diese immer auf write, sonst auf read.

Durch das lazy loading der Datenbankverbindung in Zend in Kombination mit einem ausgefeilten Caching brauchen unsere Seiten oft gar keine Verbindung auf den Master, sondern nur eine auf den Slave. Das lässt sich natürlich sehr gut skalieren.

Wir sind mit diesem Ansatz sehr gut gefahren, bisher.

Ausblick

Im nächsten Post werde ich über Sharding und Partitionierung sprechen, inkl. einer Analyse der MySQL Bordmittel sowie selbstgebauter Lösungen. Stay tuned!

10 Responses to “Skalierung von mySQL-Datenbanken Teil 1 – Verteilung von reads und writes”

  1. Interessante Serie. Hätte mir evtl. etwas Code zum read/write Handler gewünscht. Bin gespannt auf die nächste Folge…

    Thomas

  2. Ich hätte auch gerne etwas Quellcode gesehen, das hätte dem Artikel etwas mehr Tiefgang gegeben.
    So ist es leider nur ein Artikel von vielen, der sich wenig von Anderen abhebt. Schade.

    Fabian

  3. Hallo, danke für die Hinweise!

    Ich kann dann in den nächsten Tagen Teil 1b der Serie schreiben, mit Beispielcode zu diesem Artikel.

    Jan

  4. Was macht eure Anwendung wenn der Master ausfällt? Wie wissen die Applikationsserver davon und einem möglicherweise veränderen Layout? (ex-Slave wird Master usw)

    Roland Moriz

  5. Hi Roland,

    wir kriegen eine SMS und dann geht bei uns der Alarm los!

    Ernsthaft, wir hatten mal mit einem automatischen Failover ein Split Brain Condition (beide Server denken sie wären der Master). Das hat zu einem ziemlichen Datenchaos geführt. Seit dem nehme ich die Seite lieber für einige Minuten / eine Stunde offline, bevor ich so etwas riskiere. Es kommt mit guter Hardware auch recht selten vor.

    Jan

  6. Also entscheidet ihr unterm Strich einfach selbst welche Stellen mit und ohne Lag auskommen dürfen und wählt somit den entsprechenden Server für die Selects?

    Die Probleme kommen hier später dann wieder:
    - Was ist, wenn der Master mit so vielen Connections zugebombt wird, dass er nicht mehr nach kommt?

    - Was ist wenn allein die Replikation die Clients zu e.g. 80% lahm legt?

    Metal Community

  7. […] Im privaten Blog von Jan Miczaika geht es um die Arbeit mit Technologien, in Teams, und das insbesondere im Startup-Umfeld. Kontakt?     jan -at- hitflip.de oder bei XING « Skalierung von mySQL-Datenbanken Teil 1 – Verteilung von reads und writes […]

    Managing Tech » Blog Archive » Skalierung von mySQL-Datenbanken Teil 1b – Code Beispiele zur Verteilung von reads und writes

  8. Hi, ehm, Metal Community,

    ja, genau. Das machen wir quasi per Hand.

    Zu deinen Problemen:
    - lazy loading von Zend hat hier wirklich geholfen. Das sorgt dafür, dass die connection erst aufgebaut wird, wenn man die wirklich braucht. Zusätzlich kann man darauf hinarbeiten, SQLs weg zu optimieren, damit z.B. die (teure) Verbindung zum Master gar nicht mehr notwendig ist (Stichwort Sessions).

    - Dann muss man die Daten auf mehr Server partitionieren. Der gesamte Cluster ist ja von der Write-Geschwindigkeit her so langsam wie der langsamste Kern (nicht Prozessor!) des langsamsten Slaves, wenn man nicht partitioniert.

    Jan

  9. Entschuldige den etwas unsachlichen Kommentar der jetzt folgt:

    Wenn ich mir den (sicher für PHP angemessenen) Code anschaue, bin ich froh nur noch auf Ruby zu setzen :-)

    Roland Moriz

  10. Ich wusste gar nicht, dass Ruby transparente MySQL-Skalierung kann! ;-)

    Danke für den coolen Artikel. Von Zend würde ich an der Stelle vielleicht persönlich absehen, aber das muss jeder selbst entscheiden.

    Nudge

Leave a Reply