• Manchmal, aber nur manchmal ….

    von Nils Langner am 14. Januar 2009

    Im Leben eines PHP Entwicklers kommt man häufig an den Punkt, dass man eine Aktion in regulären Abständen ausführen muss. Sei es das Aufräumen der Datenbank per Skript oder das leeren eines bestimmten Verzeichnisses. Jedem von euch werden hier bestimmt noch einige Beispiele einfallen. Der Königsweg dies zu lösen ist natürlich ein Cronjob, den man einrichtet und der bestimmte Skripte zu einer bestimmten Uhrzeit ausführt. Was aber tun, wenn keine Cronjobs zur Verfügung hat, da man nur einen „normalen“ Webspace besitzt. Ja es soll Leute geben, die keinen eigenen Server besitzen.
    Nehmen wir also an, wir wollen bei jedem tausendsten Aufruf einer Webseite etwas spezielles tun. Jetzt können wir uns einfach einen Counter definieren, den wir in der Datenbank speichern und bei jedem Aufruf der Seite um Eins nach oben zählen. Dies wären zwei Datenbankzugriffe pro Seitenaufruf. Einer zum Lesen und einer zum Schreiben. Klingt relativ viel, dafür dass wir einfach nur eine Zahl hochzählen wollen.
    Wenn man genau bei jedem 1.000sten Mal die Aktion ausführen muss, dann wird einem nichts anderes übrig bleiben, aber in den meisten Fällen genügt es auch, dass es ungefähr 1000 Aufrufe sind. Ob es jetzt 950 oder 1050 sind spielt meistens keine Rolle. Wenn dies so ist, dann sollte man einfach eine Zufallszahl zu Rate ziehen.

      if ( rand(1,1000) == 500 ) {
        doAction( );
      }

    Dieser Code verschwendet keine Datenbankzugriffe und liegt auch so ganz gut in Performance Dingen. Problem also gelöst. Das geht natürlich nur wenn der verwendete Zufallsgenerator auch gut ist und gleichmäßig seine Zahlen verteilt, aber davon gehen wir hier mal aus.

    Nils Langner Nils Langner

    Auch wenn Ihr es mir nicht glauben werdet, aber ich habe nichts gegen PHP. Ich rege mich einfach nur gerne auf. Ok so schlimm ist es auch nicht. Eigentlich wollte ich schon immer einen Blog haben und da ...

    Zum Profil von Nils Langner

    10 Kommentare »


    • kb
      am 14. Januar 2009 um 09:20 Uhr

      Witzig. So hab ich das noch gar nicht in Erwägung gezogen. Da sieht man mal wie die Denkstrukturen schon eingefahren sind :)


    • Sebastian
      am 14. Januar 2009 um 09:22 Uhr

      Warum nicht die allseits bekannten “Inline-Cronjobs”? In der Datenbank wird dazu ganz normal (wie auch in einer CronTab) gespeichert, wann ein Job ausgeführt werden soll.

      Mit einem Seitenaufruf wird geprüft, ob irgendwelche Jobs jetzt starten müssten oder schon vor x-minuten/stunden usw. hätten starten müssen (es aber noch nicht getan haben, weil seit dem z.B. noch kein Seitenzugriff erfolgte), die Jobs werden dann angeschmissen und es wird noch vermerkt, wann dieser Job zuletzt lief.

      Klar, ist es etwas mehr Overhead als in der Count-Lösung, aber ist sicherlich etwas flexibler. Das ganze komplett ohne Datenbank zu machen, halte ich nur bedingt für sinnvoll. Bei einfachen Aufräum-Scripten ok, bei ernsthafteren Jobs vielleicht nicht unbedingt.


    • danielj
      am 14. Januar 2009 um 09:33 Uhr

      Die rand()-Lösung ist natürlich sehr abhängig von der Anzahl der Zugriffe. Wenn mein Script zB nachts nur sehr selten aufgerufen wird ist die Wahrscheinlichkeit eines Treffers ziemlich gering. Ob das hinnehmbar ist hängt sicherlich stark vom Anwendungsfall ab.
      Eventuell wäre eine Kombination der erwähnten “Inline-Cronjobs” und der Zufallsmethode sinnvoller; ich prüfe halt nicht bei jedem Aufruf ob ein Job gestartet werden muß sondern nur mit einer gewissen (allerdings eher hohen) Wahrscheinlichkeit.


    • Salz`
      am 14. Januar 2009 um 10:27 Uhr

      Nur so eine Idee, könnte man für sowas nicht auch http://de.php.net/apc_store verwenden (Counter speichern)?


    • Dominik
      am 14. Januar 2009 um 10:30 Uhr

      Da es einige kostenlose Cronjobdienste gibt, sehe ich eigentlich keine Notwendigkeit für solche Workarounds mehr. Man muss bei der Verwendung eines solchen Dienstes natürlich Vorkehrungen treffen. Wenn man im Script sicherstellt dass es nur von einem bestimmten Host (dem Cronjob-Anbieter) abgerufen werden darf, dann ist die Wahrscheinlichkeit ungewollter Abrufe schon sehr gering.


    • Salz`
      am 14. Januar 2009 um 10:32 Uhr

      man könnte allerdings auch einfach nach jedem durchführen über apc_store eine Variable mit TTL 24h (oder was man benötigt) anlegen, und kontrolliert dann nur noch ob die Variable vorhanden ist.

      ps: warum gibt’s hier kein editieren?


    • admin
      am 15. Januar 2009 um 07:29 Uhr

      Die apc_store Methode macht mich neugierig. Vielleicht will Salz ja was in seinem Blog was drüber schreiben. Hier geht natürlich auch.


    • Peter Rother
      am 16. Januar 2009 um 11:55 Uhr

      Auf APC zuzugreifen ist hierbei bestimmt eine nette Lösung, jetzt kommt das aber. Falls der User schon keine Cronjobs zur verfügung hat, wir er bestimmt auch die kein PECL installieren können und dies ist für APC ja Vorraussetzung.


    • cortex
      am 19. Januar 2009 um 15:20 Uhr

      besser mt_rand( ) verwenden, wenn’s um gleichverteilte zufallszahlen geht. wir hatten vor einiger zeit einen thread zu diesem thema bei selfphp. schau dir mal die grafiken in meinem post an:

      http://www.selfphp.de/forum/showthread.php?t=20507

      cx


    • Stefan
      am 23. Januar 2009 um 00:57 Uhr

      Alles ganz nett. Immerhin gibt es noch die Möglichkeit von kostenlosen Cronjobs, wenn diese auch recht unzuverlässig sind, und immer seltener werden. Auch bei größeren Communitys mit vielen Zugriffen rund um die Uhr würde ich mich nicht unbedingt auf die pünktliche Ausführung bei wichtigen Anwendungen verlassen.

      Ein Programmierer sollte doch die nötigen Verbindungen zu anderen Gleichgesinnten haben, bei denen man sich so etwas ausleihen kann. ;)

    RSS-Feed für Kommentare zu diesem Artikel. TrackBack-URL

    Einen Kommentar hinterlassen

    Werbung
    PHP Magazin
    Ausgabe 02/2010

    Dieses Mal mit Artikeln zu den Themen OpenSocial und Apache Shindig, Graphentheorie, Smarty3

    t3n
    Ausgabe 19

    Social Media (R)evolution. Weitere Themen sind noSQL, Crowdsourcing ...

    PHP Journal
    Ausgabe 2/2010

    PHP & Windows optimal nutzen, die besten PHP-CMS im Überblick, Google-API mit Zend Framework nutzen.

    Wir wurden schon öfters gefragt, ob man uns nicht irgendwie unterstützen kann. Die Antwort war immer einfach: Klar! Am einfachsten ist es eure nächsten Einkäufe bei Amazon über unsere Link abzuwickeln. Damit würdet ihr uns schon sehr helfen. Über Co-Autoren freuen wir uns aber noch mehr.