Wie kann ich die meisten Jobs parallel verarbeiten, aber eine Teilmenge serialisieren?

9

Wir erhalten gleichzeitige Rückrufe zu unserer Webanwendung von einem Anbieter, und wir vermuten, dass uns Updates verloren gehen, weil sie gleichzeitig auf verschiedenen Computern verarbeitet werden.

Wir müssen die Verarbeitung dieser Aufrufe serialisieren, genau dann, wenn sie denselben Benutzerdatensatz betreffen.

Ein Kollege von mir hat einen AWS Kinesis-Stream vorgeschlagen, bei dem wir die Benutzer-ID als Partitionsschlüssel verwenden. Die Idee ist, dass der gleiche Partitionsschlüssel den Datensatz im selben Shard platziert. Jeder Shard wird nur von einem einzelnen Worker verarbeitet, und es gibt keine Nebenläufigkeitsprobleme. Es wird garantiert, dass Datensätze, die zu demselben Benutzer gehören, nicht parallel verarbeitet werden. Diese Lösung skaliert und löst das Problem, aber es bringt uns mindestens einen Sprint zurück.

Wir versuchen, eine Lösung zu finden, die wir schneller bereitstellen können.

Andere Lösungen, die wir bisher besprochen haben:

  1. Verzögern Sie einfach die Verarbeitung der Callbacks, möglicherweise um einen zufälligen Zeitraum. In diesem Szenario ist es immer noch möglich (wenn auch weniger wahrscheinlich), dass mehrere Worker gleichzeitig Aufträge für denselben Benutzer verarbeiten.
  2. Jedes Warteschlangensystem hat den Fehler, dass wir entweder auf einen Arbeiter beschränkt sind oder die Parallelverarbeitung riskieren oder wie in (1) beschrieben.

Wir sind auf einem Rails-Stack mit MySQL und bevorzugen AWS für unsere Lösungen.

Gibt es eine Lösung für dieses Problem, die schnellere Ergebnisse liefert als den Wechsel zu Kinesis?

    
awendt 23.04.2015, 10:28
quelle

2 Antworten

0

Sie suchen im Grunde nach benannten verteilten Sperren, damit Sie die serielle Verarbeitung erzwingen können.

Wenn Sie in AWS sind, können Sie mit jeder customerId einen Datensatz nach DynamoDB übertragen.

Jedes Mal, wenn Sie einen Datensatz für die Verarbeitung erhalten, führen Sie einen konsistenten Lesevorgang durch (siehe den Abschnitt "Parallelität" hier: Ссылка ).

Wenn ein Datensatz vorhanden ist, fügen Sie ihm eine Nachricht hinzu (konsistentes Schreiben). Lassen Sie den Prozess, der gerade verarbeitet wird, einen Lesevorgang durchführen, und führen Sie, wenn dem Dynamo-Datensatz Nachrichten angehängt sind, diese seriell aus. Schließlich löschen Sie den Datensatz.

Es ist möglich, dass du die Rennbedingungen bekommst, also musst du ein Back-Off machen und es erneut versuchen. Ich weiß nicht, wie groß dein Volumen ist, aber Dynamo ist ziemlich schnell, also ist die Wahrscheinlichkeit, dass du mehr als ein paar Mal schlägst, gering. Wenn es zu oft fehlschlägt, müssen Sie möglicherweise Dinge zum Bereinigen in eine Fehlerwarteschlange ablegen, aber das ist ziemlich unwahrscheinlich. Vor allem, wenn Ihr Volumen Ihnen erlaubt, Lösungen wie willkürliche Verzögerung in der Nachrichtenverarbeitung zu betrachten.

    
Rob Conklin 24.04.2015 23:21
quelle
0

Nur eine theoretische Eingabe:

Wenn Sie Callbacks haben, die technisch unabhängig sind, benötigen Sie eine semantische Kennung, die sie als abhängig oder unabhängig kennzeichnet, und eine Sequenz-ID, die die Ausführungsreihenfolge sicherstellt. Die Benutzer-ID ist nicht ausreichend. Wie können Sie die ordnungsgemäße Reihenfolge der Datenbankausführung paralleler Webanforderungen eines Benutzers sicherstellen?

Wenn Sie eindeutige Transaktions-IDs haben, können Sie Isolationsstufen wie die Serialisierung anwenden. Aber in diesem Fall sind Sie auch gegen "Ihre" verlorenen Updates nicht unverwundbar. Sie werden auch auftreten, wenn Sie die Serialisierung verwenden, es sei denn, Sie haben keine Sequenznummer (Version) und keinen Sperrmechanismus.

Seien Sie sicher, dass Sie über "Überschreiben nicht festgeschriebener Daten" sprechen, wenn Sie "verlorene Updates" meinen, um Missverständnisse zu vermeiden. Dies wird mindestens mit Isolationsstufe "wiederholbares Lesen" behandelt.

    
oopexpert 09.05.2015 18:31
quelle