friend: memcached - ist mein erstelltes locking falsch?

hey.

Um vor gleichzeitigkeitsproblemen zu schützen, locke ich meine aktionen:

while(true===$mem->add('key',true,1)){  
  
// DO STUFF  
  
}  
$mem->delete('key');

Denke ich falsch oder ist das richtig so?

Lg, Phil

  1. Hello,

    Um vor gleichzeitigkeitsproblemen zu schützen, locke ich meine aktionen:

    while(true===$mem->add('key',true,1)){

    // DO STUFF

    }
    $mem->delete('key');

      
    Warum while?  
    Ich hätte jetzt if benutzt.  
      
    Und um das if ggf. noch eine Schleife mit Zähler (z.B. bis 5) und Waretezeit für wiederholten Versuch.  
      
      
      
      
      
    Liebe Grüße aus dem schönen Oberharz  
      
      
    Tom vom Berg  
    ![](http://selfhtml.bitworks.de/Virencheck.gif)  
      
    
    -- 
     ☻\_  
    /▌  
    / \ Nur selber lernen macht schlau  
    <http://bergpost.annerschbarrich.de>
    
    1. Warum while?

      Ich hätte jetzt if benutzt.

      Und um das if ggf. noch eine Schleife mit Zähler (z.B. bis 5) und Waretezeit für wiederholten Versuch.

      Ich dachte durch das while probiert er es unendlich oft - das soll er nämlich.
      Er _muss_ reinschreiben. Vorher darf es nicht weitergehen.

      1. Hello,

        Warum while?

        Ich hätte jetzt if benutzt.

        Und um das if ggf. noch eine Schleife mit Zähler (z.B. bis 5) und Waretezeit für wiederholten Versuch.

        Ich dachte durch das while probiert er es unendlich oft - das soll er nämlich.
        Er _muss_ reinschreiben. Vorher darf es nicht weitergehen.

        Wer ist "er"?
        Und warum fragst Du dann nach "while(true)"? und nicht nach "while(false)"?

        oder habe ich da jetzt was verkehrt verstanden?

        http://php.net/manual/en/memcache.add.php sagt:
        "Memcache::add() stores variable var with key only if such key doesn't exist at the server yet"

        Die Variable wir also nur dann beschrieben, wenn der Schlüssel nicht existiert.
        Wenn der Schlüssel existiert, ist bereits jemand anders an der Variablen dran, wenn der eigene Prozess nicht verschlafen hat, sich das zu merken, dass er es selber war...

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. oder habe ich da jetzt was verkehrt verstanden?

          http://php.net/manual/en/memcache.add.php sagt:
          "Memcache::add() stores variable var with key only if such key doesn't exist at the server yet"

          Die Variable wir also nur dann beschrieben, wenn der Schlüssel nicht existiert.
          Wenn der Schlüssel existiert, ist bereits jemand anders an der Variablen dran, wenn der eigene Prozess nicht verschlafen hat, sich das zu merken, dass er es selber war...

          Hmmm.. aber er soll es ja nur machen können wenn das hinzufügen erfolgreich war. Angenommen jemand anderes ist an der variable dran. Dann wäre add === false. Wenn ich dann auf while(false===$mem->add()) machen würde, würde er doch das was in der While-Schleife steht, genau dann ausführen, wenn jemand anderes dran ist oder?
          Bin ich gerade blind&Blöd&überarbeitet?

          1. Hello,

            oder habe ich da jetzt was verkehrt verstanden?

            http://php.net/manual/en/memcache.add.php sagt:
            "Memcache::add() stores variable var with key only if such key doesn't exist at the server yet"

            Die Variable wir also nur dann beschrieben, wenn der Schlüssel nicht existiert.
            Wenn der Schlüssel existiert, ist bereits jemand anders an der Variablen dran, wenn der eigene Prozess nicht verschlafen hat, sich das zu merken, dass er es selber war...

            Hmmm.. aber er soll es ja nur machen können wenn das hinzufügen erfolgreich war. Angenommen jemand anderes ist an der variable dran. Dann wäre add === false. Wenn ich dann auf while(false===$mem->add()) machen würde, würde er doch das was in der While-Schleife steht, genau dann ausführen, wenn jemand anderes dran ist oder?
            Bin ich gerade blind&Blöd&überarbeitet?

            Ich weiß zwar immer noch nicht, wer "er" ist. Aber wie oft soll denn die Variable benutzt werden? Ich rate jetzt mal, genau einmal. Sie soll aber nur beschrieben werden können, wenn gerade kein anderer Prozess an der Variable dran ist. Das wird signalisiert (Semaphor=Signal) durch das Signal. Ist das Signal gesetzt (vorhanden), wird die Variable von einem anderen Prozess gesetzt. Dann darf dein Prozess kein Signal setzten, denn es ist schon da.

            Solange also ein Signal vorhanden ist, kann kein eigenes erstellt werden. Solange _kein_ eigenes ertellt werden kann, muss also versucht werden, eines zu erstellen. Erst, wenn ein eigenes Signal erstellt werden konnte, darf geschrieben werden.

            ---->solange (kein_eigenes_Signal_erstellt_werden_kann) --+
                  ^                                                       |
                  +-------------------------------------------------------+

            anschließend_verändere_die_Variable;

            nimm_das_Signal_wieder_weg;

            So muss es aussehen!

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. ---->solange (kein_eigenes_Signal_erstellt_werden_kann) --+
                    ^                                                       |
                    +-------------------------------------------------------+

              anschließend_verändere_die_Variable;

              nimm_das_Signal_wieder_weg;

              ACHSOO!
              DU willst ihn also in einer Schleife warten lassen. Und erst dann im Skript weitergehen.

              Es gibt in Memcache ein Array. Während einer Auktion kann es sein das in den leztten Sekunden 300 Menschen klicken. Bei jedem Klick würde dieses Array verändert werden (das was bei mir aktuell IN der While-Schleife steht). Was passiert wenn 2 das gleichzeitig tun, ist denke ich klar.

              Also so wie ich es gemacht habe geht es gar nicht?
              Liege irgendwie echt auf dem Schlauch heute.

              1. Hello,

                ---->solange (kein_eigenes_Signal_erstellt_werden_kann) --+
                      ^                                                       |
                      +-------------------------------------------------------+

                anschließend_verändere_die_Variable;

                nimm_das_Signal_wieder_weg;

                ACHSOO!
                DU willst ihn also in einer Schleife warten lassen. Und erst dann im Skript weitergehen.

                Den Besucher?
                Das oben beschriebene ist ein "Blocking Lock".
                Begriffsbestimmung z.B.: http://msdn.microsoft.com/en-us/library/aa266504(VS.60).aspx

                Es gibt in Memcache ein Array. Während einer Auktion kann es sein das in den leztten Sekunden 300 Menschen klicken. Bei jedem Klick würde dieses Array verändert werden (das was bei mir aktuell IN der While-Schleife steht).

                In der While-Schleife ist es falsch, wenn das Stück Code, das Du uns vor den Latz geknallt hast, Bestandteil eines (jedes!) Client-Prozesses ist.

                Was passiert wenn 2 das gleichzeitig tun, ist denke ich klar.

                Klar, derjenige, der zu spät kommt, muss warten in einer Schleife. Je nachdem, wie die Speicher(zugriffs)verwaltung, in deren Hoheitsbereich die Methode Memcache::add() gehört, die einzelnen Anforderungen behandelt.

                Als Expiration Time hast Du 1 Sekunde angegeben. Für einen reinen Konfliktschutz sollte das genügen, wenn der Zyklus aus den folgenden Komponenten besteht:

                -   Besorgen einer Sperre, incl. Abfrage, ob es schon eine gibt.
                    Die beiden Schritte müssen vom zuständigen System atomar gekapset sein

                -   Abfrage des alten Wertes, der durch das Semaphor (die Sperre) geschützt wird

                -   Manipulation des Wertes
                    incl, Zurückschreiben in den Shared Memory

                -   Aufheben der Sperre.

                Je nachdem, ob die Sperrfunktion selber dabei BLOCKING arbeitet, also solange das Programm anhält, bis sie Erfolg hatte (wie es z.B. flock() in der einfachsten Anwendung tut), oder ob sie NON_BLOCKING arbeitet, muss/kann man dies selber berücksichtigen im Programmfluss.

                Die Schleife, die ich Dir angedeutet habe, hat nur dann Sinn, wenn sie im Schleifenkörper ein Sleep() (oder in Deinem Fall ein uSleep() http://de3.php.net/manual/en/function.usleep.php enthält, das die Wartezeit anderen Prozessen zur Verfügung stellt. Üblicherweise bedeuten Sleep() und uSleep() bei PHP dem Prozessor (fast) keine Last. Das ist die Voraussetzung, dass Du sie hier sinnvoll einsetezen kannst.

                Also so wie ich es gemacht habe geht es gar nicht?

                Nein, es ist verkehrt herum.

                Liebe Grüße aus dem schönen Oberharz

                Tom vom Berg

                --
                 ☻_
                /▌
                / \ Nur selber lernen macht schlau
                http://bergpost.annerschbarrich.de
                1. In der While-Schleife ist es falsch, wenn das Stück Code, das Du uns vor den Latz geknallt hast, Bestandteil eines (jedes!) Client-Prozesses ist.

                  Ja ist sie. Bzw. jeder der diese URL aufruft.

                  Der Code sieht jetzt so aus:

                  while(false===$mem->add('lockkey',true,1)){}  
                    
                  // DO MANIPULATING STUFF  
                    
                  $mem->delete('lockkey');
                  

                  Warum muss ich ihm in die While-Schleife noch ein usleep setzen und wenn ja, reicht eine Milisekunde (hauptsache er hat was zu tun?).

                  Lg, Friend

                  1. Hello,

                    In der While-Schleife ist es falsch, wenn das Stück Code, das Du uns vor den Latz geknallt hast, Bestandteil eines (jedes!) Client-Prozesses ist.

                    Ja ist sie. Bzw. jeder der diese URL aufruft.

                    Der Code sieht jetzt so aus:

                      
                    while(false===$mem->add('lockkey',true,1))  
                    {  
                        usleep(5);  
                    }  
                      
                    
                    > // DO MANIPULATING STUFF  
                      
                    $mem->delete('lockkey');
                    

                    Warum muss ich ihm in die While-Schleife noch ein usleep setzen und wenn ja, reicht eine Milisekunde (hauptsache er hat was zu tun?).

                    Damit der Prozessor nicht für ein nutzloses while anfängt zu kochen.
                    Das usleep() kostet ihn erheblich weniger Rechenzeit.

                    Liebe Grüße aus dem schönen Oberharz

                    Tom vom Berg

                    --
                     ☻_
                    /▌
                    / \ Nur selber lernen macht schlau
                    http://bergpost.annerschbarrich.de
          2. Hi,

            Hmmm.. aber er soll es ja nur machen können wenn das hinzufügen erfolgreich war.

            Wenn du dir erst mal die Zeit genommen hättest, die Rückfrage

            Wer ist "er"?

            zu beantworten, dann gäbe es jetzt vermutlich weniger Missverständnisse.

            Es ist eine Anfänger-Unart, immer von „ihm“ zu reden - „er macht das nicht wie er soll“, „dann gibt er mit folgenden Fehler aus“, etc.

            Bitte vermeide das - nenne Ross und Reiter, sage klar und deutlich, welche Komponente in deinem System welches Verhalten zeigt.

            Angenommen jemand anderes ist an der variable dran.

            Definiere bitte „an der Variable dran sein“.

            Dann wäre add === false.

            add liefert dann false, wenn unter dem verwendeten Key bereits ein Eintrag existiert, ja.

            Wenn ich dann auf while(false===$mem->add()) machen würde, würde er doch das was in der While-Schleife steht, genau dann ausführen, wenn jemand anderes dran ist oder?

            Ja.

            while(true===$mem->add('key',true,1)){

            // DO STUFF

            }
            $mem->delete('key');

              
            Ob das überhaupt sinnvoll sein kann, hängt stark davon ab, was bei "DO STUFF" passiert.  
              
            Wenn du den key nicht innerhalb der Schleife wieder entfernst - dann wird sie kein zweites Mal durchlaufen, weil add beim zweiten Aufruf mit 'key' false liefern wird.  
            Dann ist eine Schleife also unsinnig, da reicht, wie anfangs schon angemerkt wurde, ein einfaches if.  
              
            MfG ChrisB  
              
            
            -- 
            RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
            
  2. Hallo friend.

    Um vor gleichzeitigkeitsproblemen zu schützen, locke ich meine aktionen:

    Wo tritt bei dir denn Nebenläufigkeit auf?

    Wenn du PHP normal ausführst (HTTP-Request -> Abarbeitung PHP-Skript -> HTTP-Response) passiert da erstmal nichts nebenläufig.

    Probleme mit gleichzeitigen/(quasi-)parallelen Zugriffen kannst du bekommen, wenn du auf externe Ressourcen zugreifst (z.B. Datenbank, Memcached, Filesystem, ...), wobei sich diese sich z.T. selbst darum kümmern.

    Also:
    Was wird bei dir nebenläufig ausgeführt?

    Servus,
    Flo

    1. Hello,

      Was wird bei dir nebenläufig ausgeführt?

      Der Kandidat OP arbeitet mit Shared Memory, weil ihm LFA (Locked File Access) zu langsam ist.

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
       ☻_
      /▌
      / \ Nur selber lernen macht schlau
      http://bergpost.annerschbarrich.de
    2. Was wird bei dir nebenläufig ausgeführt?

      Lieber Flo, was sagt dir das erste Wort in meinem Titel? ;)