Was ist der beste Weg, um eine Sperre aus einer Webanwendung zu erstellen?

8

Ich habe eine Webanwendung, die Bilder neu dimensioniert. Die vergrößerten Bilder werden auf die Festplatte geschrieben, um sie zwischenzuspeichern. Was ist der beste Weg, um zu verhindern, dass mehrere gleichzeitige Anfragen das gleiche Bild erzeugen?

Ein paar Dinge zu beachten, wir haben Millionen von Bildern (gemessen in Terabyte). Zwischengespeicherte Bilder, die längere Zeit nicht angezeigt wurden, werden entfernt. Wir haben eine Webfarm, aber jeder Webserver hat seinen eigenen lokalen Cache (die Originale sind auf einem anderen Server gespeichert). Wir platzieren die neu dimensionierten Bilder auch in einem Cache der zweiten Schicht, sobald sie generiert wurden, damit andere Webserver dort nachsehen können, ob das Bild zwischengespeichert ist. Ist dies der Fall, wird es lokal kopiert.

Ich habe überlegt, Sperren zu verwenden (Ich habe eine Klasse geschrieben, die ich in Erwägung ziehe, indem ich hier ). Aber das funktioniert offensichtlich nicht mit dem Cache der zweiten Schicht und ich bin mir nicht sicher, ob es generell eine gute Idee ist, auf einem Webserver Sperren zu verwenden (obwohl ich mir nicht sicher bin, warum, nur ein paar vage Referenzen auf es ist eine schlechte Idee).

Ich habe auch darüber nachgedacht, eine temporäre Datei zu schreiben, die ich überprüfen könnte, bevor ich mit der Erstellung des Bildes beginne, aber ich mache mir Sorgen, dass Windows die Datei nicht zu 100% richtig aufräumt (Sperrprobleme usw.).

Irgendwelche Ideen werden geschätzt.

    
Brian 13.09.2011, 00:53
quelle

8 Antworten

1

Haben Sie darüber nachgedacht, Middleware wie MSMQ oder ActiveMQ zu verwenden? Sobald die Bildgrößenänderungsanforderung an den Webserver übermittelt wurde, wird sie in die Warteschlange gestellt. Eine separate Anwendung würde die Warteschlange überprüfen, die Größe des Bildes ändern und es im Cache speichern.

    
Sergey Sirotkin 13.09.2011 02:45
quelle
1

Ich würde Sperren vermeiden, wenn Sie können - vor allem, weil Sie hier nicht sperren müssen. Sie möchten auch verhindern, dass ein Computer aufgrund einer anderen Computerverarbeitung gesperrt wird. Wenn zwei Maschinen das gleiche Bild in der Größe erzeugen, nehme ich an, dass sie identisch sind. Wenn also zwei Maschinen das gleiche Problem in der Größe ändern, weil sie beide den Cache verpassten, dann ist es nur etwas weniger effizient (verschwendete Zeit), aber sehr wahrscheinlich besser als Sperren (und möglicherweise Deadlock) und versuchen, den Randfall zu optimieren.

Eine Option wäre, das Bild in der Größe lokal zu erstellen und das zwischengespeicherte Objekt in eine zentrale Warteschlange (Datenbank? im Speicher des zentralen Dienstes?) entweder mit den Daten oder mit einer Referenz, wie es vom Front-End-Computer abgerufen wird. Die zentralisierte Cache-Warteschlange wird seriell verarbeitet. Wenn zwei Duplikate zwischen der Zeit, in der die Größe von mehr als einer Maschine geändert wird, in die Warteschlange gestellt werden und das Warteschlangenelement verarbeitet werden kann, spielt es keine Rolle, da die Verarbeitung des Duplikats lediglich eine Wiederherstellung erfordert, da es sich bereits auf der Festplatte befindet.

    
bryanmac 13.09.2011 03:43
quelle
1

Erzeuge zuerst den Dateinamen mit einer GUID, damit du weißt, dass du keine doppelten Dateinamen hast.

Guid.NewGuid ()

Verhindern Sie dann das Sperren der Bilder mit dem folgenden Code: -

%Vor%

Ich habe diesen Code sehr effektiv ausgeführt und es war der einzige Weg, um sicherzugehen, dass die Datei niemals gesperrt ist.

    
Adam O'Neil 23.09.2011 14:47
quelle
0

Das Verwenden einer Datenbank zum Auflisten von Datei-Hashes wäre der schnellste Weg, dies zu tun. Dann kann dies zwischen allen Ebenen aufgeteilt werden, und Sie können auch alle Sperren in die Transactional SQL (T-SQL) verschieben.

Andere große Anwendungen, die TB wie Symantec Enterprise Vault speichern müssen, machen dasselbe.

    
Bernie White 13.09.2011 03:42
quelle
0

Es sollte von Web-Anwendungen nicht anders sein, die die Bearbeitung / Aktualisierung der Daten in einer Datenbank steuern müssen.

Soweit ich es versucht habe, wurde das Bild erfolgreich als Blob-Feld in der Datenbank gespeichert. Ich ließ die Blob-Bearbeitung genau so steuern wie jedes andere Datenfeld.

Das bedeutet, Sie mit vertraut sein, wie Web-Service arbeitet mit der Datenbank mit Kollisionen und Gleichzeitigkeitssteuerung zu beschäftigen.

Als Alternative Wenn Sie sich keine hochskalierbaren rdbms leisten können ... Anstatt als Blob in der Datenbank zu speichern, könnten Sie den Dateinamen / Pfad speichern, in dem das aktuelle Bild im Dateisystem gespeichert ist. Die Datenbank stellt den eindeutigen Schlüssel für ein Bild bereit. Alle Zugriffe auf ein beliebiges Bild müssen über den Datenbankeintrag erfolgen. Jedes Mal, wenn ein neues Bild erzeugt wird, findet unter einer atomaren Transaktion in der vorgeschriebenen Reihenfolge Folgendes statt:

  1. es wird unter einem neuen Namen / Pfad
  2. gespeichert
  3. Wenn erfolgreich, wird der Datenbankdatensatz aktualisiert
  4. Wenn erfolgreich, wird das alte Bild gelöscht

Dies ist die Eventualitäten Sie behandeln müssen: wenn der letzte Schritt nicht erfolgreich ist (System / Stromausfall sein kann), würde der db Rekord aufgerollt werden zurück und Sie würden eine Waise Bild haben. Oder, falls die Datenbankaktualisierung fehlschlägt, würde das neu gespeicherte Bild als verwaist enden.

Daher halten Ihr Dateisystem gesund und Waisen wegzuräumen, werden Sie wahrscheinlich Bilder löschen, die älter sind als 24 Stunden.

Eine stabilere Lösung finden Sie in der Beschreibung meiner Web-App-Caching-Technik:

Ссылка

    
Blessed Geek 13.09.2011 03:44
quelle
0

Ich würde zwei Lösungen vorschlagen, die in der Natur ähnlich sind. Eine davon ist die Verwendung einer WCF-Dienstschicht. Innerhalb dieses Service können Sie ein Concurrent Dictionary verwenden. Sie sollten einen Hash-Code so entwickeln, dass dasselbe Bild den gleichen Hash erzeugt. Daher haben Sie eine einzelne Instanz des Bildes in Ihrem Concurrent Dictionary. Sie können Ihrer Klasse auch einen Zeitstempel hinzufügen, der das Bild darstellt. Es könnte nützlich sein. Sobald Sie das Bild erstellt haben, können Sie diese Klasse in Ihrer Klasse mit dem Speicherort des generierten Bildes aktualisieren. und Sie können eine große Flagge haben, die anzeigt, dass dieses Bild verarbeitet wird, wenn Sie eine weitere Anfrage haben, die nach einer Größenänderung fragt. dann ignorierst du diese Anfrage. Nicht nur, dass Sie ein Concurrent-Wörterbuch verwenden, Sie können auch einen einzelnen Schlüssel innerhalb des Wörterbuchs wieder sperren. Wenn Sie jedoch ein Bit-Flag als CurrentProcessing verwenden, brauchen Sie keine Sperre. Dies wäre eine sehr schnelle und effiziente Lösung, IMO.

Eine andere Lösung wäre eine verteilte Hash-Tabelle wie AppFabric-Cache. Gleiche Logik wie oben.

Was denkst du?

    
DarthVader 15.09.2011 02:40
quelle
0

Ich bin mir nicht sicher, ob Sie diesen Punkt wirklich lösen müssen - beachten Sie die folgenden Punkte:

  • Was passiert, wenn ein Server anfängt, die Größe eines bestimmten zu ändern und der Resiszing-Prozess irgendwie "hängen bleibt"? Wenn Sie das implementieren, was Sie beschreiben, warten alle anderen Server darauf, dass dieser Server beendet wird ... nicht sicher, dass dies für eine gute Benutzererfahrung sorgt
  • OTOH, wenn Sie nicht implementieren, dass Sie nur ein wenig Zeit verlieren, aber nicht mit der Lösung des oben genannten Problems konfrontiert sind ...

Ich würde definitiv eine Art von entweder DB oder (zentralen) In-Memory-Cache der Inhalte (Bild-IDs) des 2nd-Tier-Caches implementieren, damit Avoud-Maschinen beim Kopieren des skalierten Bilds in die Cache ...

    
Yahia 15.09.2011 03:26
quelle
0

Wenn Sie möchten, dass ein Client ein zufälliges Bild zu einem Zeitpunkt verarbeiten kann, speichern Sie zuerst ein Flag im Viewstate, wenn Sie die Anfrage erhalten. Das Flag wird ausgelöst, wenn die Daten gesendet werden, und das Flag wird zurückgesetzt, wenn Sie die Verarbeitung des Bilds abgeschlossen haben. Wenn Sie eine Anfrage erhalten, prüfen Sie, ob die Flagge erhöht ist oder nicht. Wenn ausgelöst, lehnen Sie ab, um das Bild zu verarbeiten.

Wenn Sie zweitens vorgeben möchten, dass der Benutzer das gleiche Bild einreicht, können Sie den Namen und die Größe (byteweise) des Bildes im Viewstate speichern. Wenn der Benutzer ein Bild auswählt, vergleicht man Name und Größe des Bildes Bild, bevor Sie das Bild bearbeiten. Wenn die Größe und der Name des Bildes mit denen identisch sind, die Sie im Viewstate gespeichert haben, lehnen Sie die Verarbeitung des Bildes ab. andernfalls verarbeitest du es.

Ich hoffe, es kann Ihnen helfen.

    
Ozgur Dogus 23.09.2011 13:23
quelle

Tags und Links