Facebook
Twitter
Google+
Kommentare
10

Manchmal, aber nur manchmal ….

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.

Über den Autor

Nils Langner

Nils Langner ist der Gründer von "the web hates me" und auch der Hauptautor. Im wahren Leben leitet er das Qualitätsmanagementteam im Gruner+Jahr-Digitalbereich und ist somit für Seiten wie stern.de, eltern.de und gala.de aus Qualitätssicht verantwortlich. Nils schreibt seit den Anfängen von phphatesme, welches er ebenfalls gegründet hat, nicht nur für diverse Blogs, sondern auch für Fachmagazine, wie das PHP Magazin, die t3n, die c't oder die iX. Nebenbei ist er noch ein gern gesehener Sprecher auf Konferenzen. Herr Langner schreibt die Texte über sich gerne in der dritten Form.
Kommentare

10 Comments

  1. 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.

    Reply
  2. 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.

    Reply
  3. 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.

    Reply
  4. 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?

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

    Reply
  6. 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.

    Reply
  7. 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. 😉

    Reply

Leave a Comment.

Link erfolgreich vorgeschlagen.

Vielen Dank, dass du einen Link vorgeschlagen hast. Wir werden ihn sobald wie möglich prüfen. Schließen