Odśmiecanie danych na stronie WWW: porównanie podejść
Strony internetowe w trakcie działania generują różnego rodzaju dane tymczasowe — cache, sesje, tymczasowe pliki, wpisy w bazie danych itd. Choć są one przydatne w kontekście wydajności i działania aplikacji, z czasem mogą urosnąć do niekontrolowanych rozmiarów. Odśmiecanie (ang. garbage collection) tego typu danych jest niezbędne, by utrzymać sprawność, szybkość i bezpieczeństwo aplikacji webowej.
W tym artykule porównamy dwa popularne podejścia do odśmiecania danych:
- Losowe odśmiecanie przy okazji żądań użytkowników
- Regularne zadania CRON
Co należy odśmiecać?
W zależności od systemu i aplikacji, typowe elementy do odśmiecania to:
- Cache aplikacji (pliki lub dane w bazie)
- Sesje użytkowników, które wygasły
- Tymczasowe pliki (np. uploady, pliki robocze)
- Logi starsze niż określony czas
- Dane w bazie, np. stare tokeny, wygasłe linki, niepotwierdzone konta
Podejście 1: Losowe odśmiecanie na podstawie requestów
Jak to działa?
Mechanizm losowy polega na tym, że z pewnym prawdopodobieństwem (np. 1 na 100 requestów) serwer wykonuje odśmiecanie. Takie podejście często można spotkać np. w PHP (session.gc_probability
i session.gc_divisor
).
Zalety:
- Brak potrzeby ustawiania dodatkowych zadań CRON
- Zadziała automatycznie nawet na serwerach bez dostępu do CRON
- Proste do implementacji
Wady:
- Nierówna częstotliwość — zależna od ruchu na stronie
- W mało ruchliwych serwisach odśmiecanie może być zbyt rzadkie
- W czasie jednego requestu może dojść do opóźnienia użytkownika
Przykład ustawień:
Jeśli chcesz uruchamiać odśmiecanie średnio co 100 żądań:
define('GC_CHANCE', 100);
if (mt_rand(1, GC_CHANCE) === 1) {
garbage_collect();
}
Dla większych serwisów o dużym ruchu warto zmniejszyć częstotliwość, np. 1 na 1000 requestów. Dla mniejszych — nawet 1 na 10.
Podejście 2: CRON — zadania cykliczne
Jak to działa?
CRON to systemowy harmonogram zadań, który może cyklicznie uruchamiać skrypt odśmiecania np. raz dziennie lub co godzinę.
Zalety:
- Niezależne od ruchu — działa nawet przy zerowym ruchu
- Stabilna, przewidywalna częstotliwość
- Może wykonywać bardziej zasobożerne czyszczenie (np. indeksowanie, backupy)
Wady:
- Wymaga dostępu do CRON lub narzędzia typu scheduler (np. Laravel Scheduler)
- Może nie być dostępne na niektórych hostingach współdzielonych
- Może wymagać dodatkowego monitoringu działania
Przykład wpisu w CRON (raz dziennie o 3:00):
0 3 * * * /usr/bin/php /var/www/html/artisan schedule:run >> /var/log/cron.log 2>&1
Co wybrać?
Kryterium | Losowe requesty | Zadanie CRON |
---|---|---|
Łatwość wdrożenia | Bardzo proste | Wymaga dostępu do CRON |
Skuteczność | Zależna od ruchu | Zawsze regularna |
Obciążenie serwera | Może wpływać na usera | Zależne od harmonogramu |
Stabilność działania | Niska przy małym ruchu | Wysoka |
Rekomendacje
- Dla prostych stron, blogów, landing page’y – losowe czyszczenie może być wystarczające, np. 1 na 50–100 requestów.
-
Dla większych serwisów i aplikacji – lepszym wyborem będzie CRON, z częstotliwością:
- Sesje, cache – co godzinę lub co 6 godzin
- Logi, pliki tymczasowe, tokeny – raz dziennie
- Backupy, indeksowanie – co tydzień
Emulacja zadań CRON
Aby emulować działanie zadania CRON, bazując na ruchu użytkowników, możesz stworzyć system, który uruchamia akcję odśmiecania mniej więcej co godzinę, bez użycia systemowego CRON-a.
Poniżej przedstawiam pełne rozwiązanie, które:
- zapisuje ostatni czas wykonania odśmiecania,
- sprawdza przy każdym żądaniu, czy minęła określona ilość czasu (np. godzina),
- uruchamia czyszczenie tylko raz, bez względu na to, ilu użytkowników wejdzie w tym samym czasie.
Rozwiązanie: Emulacja CRON co godzinę z użyciem pliku blokady (lockfile)
Zalety:
- Nie wymaga CRON-a
- Działa przy umiarkowanym ruchu
- Odśmiecanie wykonuje się tylko raz na określony czas
- Bezpieczne w środowisku współdzielonym (np. shared hosting)
Przykład w PHP:
function emulate_cron($interval_seconds, callable $task, $lock_file = '/tmp/emulated_cron.lock') {
$now = time();
// Sprawdź czy plik istnieje
if (file_exists($lock_file)) {
$last_run = (int)file_get_contents($lock_file);
// Jeśli nie minął jeszcze interwał – nie rób nic
if (($now - $last_run) < $interval_seconds) {
return;
}
}
// Próbujemy zapisać nowy czas
if (file_put_contents($lock_file, $now, LOCK_EX) !== false) {
// Wykonaj zadanie
$task();
}
}
Użycie:
emulate_cron(3600, function() {
// Wstaw tutaj logikę odśmiecania
cleanup_sessions();
cleanup_temp_files();
cleanup_cache();
});
Uwagi techniczne:
LOCK_EX
zapobiega konfliktom przy równoczesnym zapisie.- Domyślnie plik blokady jest zapisywany w
/tmp
, ale możesz go przenieść np. do katalogu projektu (__DIR__ . '/cron.lock'
). - Przy niskim ruchu (np. 1 użytkownik co 3 godziny), czyszczenie może uruchamiać się rzadziej — ale nadal z zachowaniem logiki CRON-a.
- W środowisku z wieloma serwerami (np. load balancer), użyj bazy danych lub systemu wspólnego cache (Redis/Memcached) zamiast pliku.
Bonus: Dostosowanie do liczby użytkowników
Jeśli chcesz uwzględnić częstotliwość odwiedzin, możesz:
- zwiększyć częstotliwość sprawdzania, np. co 10 minut (
600 sekund
) - lub ustawić odśmiecanie co N requestów i co określony czas:
define('GC_REQUEST_INTERVAL', 500);
define('GC_TIME_INTERVAL', 3600);
session_start();
if (!isset($_SESSION['gc_count'])) {
$_SESSION['gc_count'] = 0;
}
$_SESSION['gc_count']++;
if ($_SESSION['gc_count'] >= GC_REQUEST_INTERVAL) {
$_SESSION['gc_count'] = 0;
emulate_cron(GC_TIME_INTERVAL, function() {
cleanup_sessions();
});
}
Jak dynamicznie ustalić optymalną częstotliwość odśmiecania?
Aby dobrać optymalną częstotliwość losowego odśmiecania (np. 1 na N requestów), możemy napisać skrypt w PHP, który:
- Zlicza liczbę wejść (żądań) w ciągu ostatniej godziny (lub innego przedziału czasu),
- Na tej podstawie wylicza, co ile requestów powinno losowo wywoływać czyszczenie, by zdarzało się to średnio raz na godzinę,
- Proponuje wartość N, którą można ustawić np. jako
GC_CHANCE
.
Wymagania:
- Prosty zapis requestów do pliku lub bazy (dla trwałości)
- Brak zewnętrznych bibliotek — czyste PHP
Koncepcja:
Zapisujemy timestamp każdego requestu (np. UNIX time) do pliku (można też użyć bazy danych). Na tej podstawie analizujemy, ile requestów było w ostatniej godzinie, i wyliczamy optymalny współczynnik odśmiecania.
Kod PHP – zapisywanie i analiza requestów
define('HISTORY_FILE', __DIR__ . '/request_log.txt');
define('GC_TARGET_INTERVAL', 3600); // docelowy czas między czyszczeniami (1h)
/**
* Zarejestruj request
*/
function log_request() {
$now = time();
file_put_contents(HISTORY_FILE, $now . PHP_EOL, FILE_APPEND | LOCK_EX);
}
/**
* Policz requesty z ostatniej godziny i zaproponuj interwał
*/
function get_optimal_gc_chance($target_interval = GC_TARGET_INTERVAL) {
$now = time();
$threshold = $now - $target_interval;
$lines = @file(HISTORY_FILE, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (!$lines) return 100; // domyślnie
// Odfiltruj tylko ostatnią godzinę
$recent = array_filter($lines, function($ts) use ($threshold) {
return is_numeric($ts) && (int)$ts >= $threshold;
});
$request_count = count($recent);
if ($request_count === 0) return 1; // bardzo mały ruch
// Chcemy, żeby czyszczenie odbywało się 1x na godzinę
$chance = (int) ceil($request_count);
return max($chance, 1);
}
Przykład użycia:
log_request(); // rejestrujemy request
$gc_chance = get_optimal_gc_chance(); // np. zwraca 80
if (mt_rand(1, $gc_chance) === 1) {
garbage_collect(); // wykonujemy czyszczenie
}
Dodatek: Czyszczenie starego logu (co kilka dni)
Aby plik request_log.txt
nie urósł za bardzo, warto co jakiś czas go oczyścić:
function cleanup_request_log($max_age_seconds = 7 * 86400) {
$now = time();
$threshold = $now - $max_age_seconds;
$lines = @file(HISTORY_FILE, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (!$lines) return;
$filtered = array_filter($lines, function($ts) use ($threshold) {
return is_numeric($ts) && (int)$ts >= $threshold;
});
file_put_contents(HISTORY_FILE, implode(PHP_EOL, $filtered) . PHP_EOL, LOCK_EX);
}
Pzykład: Jak to działa w praktyce?
- Jeśli w ciągu godziny było 150 requestów, losowe czyszczenie będzie uruchamiane średnio raz na 150 requestów, czyli raz na godzinę.
- Jeśli strona ma tylko 10 requestów na godzinę, czyszczenie będzie uruchamiane średnio co 10 requestów, czyli raz na 1–2 dni.
Podsumowanie
Odśmiecanie danych to kluczowy element utrzymania zdrowia aplikacji webowej. Dla mniejszych stron prostsze podejście oparte na losowości może być wystarczające, jednak w przypadku serwisów o większym znaczeniu lub wymaganiach operacyjnych, CRON zapewnia stabilność i przewidywalność działania.
Najlepszym rozwiązaniem bywa często hybryda – podstawowe czyszczenie (np. sesji) za pomocą losowych requestów, a bardziej kompleksowe działania przez CRON.
Emulacja CRON-a przez plik z czasem ostatniego uruchomienia to efektywne rozwiązanie dla środowisk bez dostępu do systemowego CRON-a. Jest deterministyczne, odporne na powielanie i działa niezależnie od liczby requestów — tak długo, jak strona ma umiarkowany ruch.
Dynamiczna optymalizacja dopasowuje częstotliwość losowego czyszczenia do ruchu na stronie, osiągając docelowy interwał (np. godzinny). Działa na każdej stronie z umiarkowanym ruchem i nie wymaga CRON-a. W razie potrzeby możemy przenieść logi do bazy danych lub Redis dla większej skali.