Position actuelle: Accueil> Derniers articles> Comment éviter les problèmes de race de données dans l'utilisation d'APCU_ENTRY

Comment éviter les problèmes de race de données dans l'utilisation d'APCU_ENTRY

gitbox 2025-05-26

La compétition de données fait référence à plusieurs processus ou threads qui accédaient aux données partagées en même temps, et au moins un processus ou un thread écrit les données, ce qui entraîne des résultats d'exécution instables du programme ou un comportement imprévisible. En PHP, en particulier lors de l'utilisation du cache APC, car les données en cache sont généralement partagées à l'échelle mondiale, si plusieurs demandes écrivent sur la même clé de cache en même temps, des problèmes de course de données peuvent se produire.

Problèmes de course de données lorsque vous utilisez APCU_ENTRY

La fonction de la fonction APCU_ENTRY est de vérifier s'il existe déjà des paires de valeurs de clé spécifiées dans le cache. Sinon, il exécute une fonction de rappel pour générer les données et les stocker dans le cache. Dans des circonstances normales, il peut éviter efficacement le problème de calcul en double de l'échec du cache, mais dans des scénarios simultanés, si plusieurs demandes fonctionnent sur la même clé de cache en même temps, les problèmes suivants peuvent être causés:

  1. Calcul répété : lorsque plusieurs demandes sont simultanées, bien que le cache n'atteigne pas, plusieurs demandes peuvent entrer la fonction de rappel en même temps et calculer le même résultat à plusieurs reprises, ce qui entraîne un gaspillage de ressources.

  2. Incohérence : Étant donné que les opérations de cache sont effectuées dans les fonctions de rappel, les opérations simultanées peuvent provoquer un écrasement ou une incohérence des données.

Comment éviter la compétition de données?

Afin de résoudre le problème de la concurrence des données, l'utilisation d' APCU_ENTRY peut être optimisée de la manière suivante:

1. Utilisez le mécanisme de verrouillage

Le moyen le plus courant consiste à utiliser un mécanisme de verrouillage pour s'assurer qu'un seul processus peut effectuer des écritures de cache à la fois. Dans PHP, vous pouvez utiliser des verrous de fichiers, redis, memcached, etc. pour implémenter des verrous. Voici une simple implémentation de l'utilisation de verrous de fichiers:

 $cache_key = 'my_cache_key';
$lock_key = $cache_key . '_lock';

if (apcu_exists($lock_key)) {
    // Si la serrure existe déjà,Attendez un moment et réessayez
    sleep(1);
} else {
    // Ajouter un verrouillage
    apcu_store($lock_key, true, 10); // Le temps d'expiration de verrouillage est10Deuxième

    // Générer des valeurs mises en cache
    $value = generate_cache_value();

    // Stocker des valeurs mises en cache
    apcu_store($cache_key, $value);

    // Relâchez le verrouillage
    apcu_delete($lock_key);
}

En utilisant des verrous, nous pouvons nous assurer qu'en même temps, un seul processus peut entrer dans la logique de rappel générée par le cache, évitant ainsi les calculs répétés.

2. Utilisez APCU_ADD au lieu d' APCU_ENTRY

La fonction APCU_ADD est similaire à la fonction APCU_ENTRY , mais il évite d'écraser les valeurs de cache existantes. Ainsi, lorsque vous avez juste besoin de vous assurer que la clé de cache existe, vous pouvez utiliser APCU_ADD pour réduire les risques de concours de données.

 $value = apcu_add('my_cache_key', generate_cache_value(), 3600);

Si la clé de cache existe déjà, APCU_ADD ne l'écrasera pas, réduisant ainsi les conditions de course générées pendant la concurrence.

3. Vérifiez le cache à l'avance

Un autre moyen simple consiste à vérifier si le cache existe déjà avant d'entrer dans la fonction de rappel, évitez les calculs répétés lorsque plusieurs demandes sont exécutées simultanément. Un drapeau séparé peut être utilisé pour enregistrer si le cache est calculé ou a été calculé. Par exemple:

 $cache_key = 'my_cache_key';

if ($result = apcu_fetch($cache_key)) {
    // Frappe du cache,Utiliser directement
} else {
    // Cache miss,Vérifiez l'état de calcul
    $status_key = $cache_key . '_status';
    if (!apcu_exists($status_key)) {
        // Aucun signe calculé,Marquez comme calculant
        apcu_store($status_key, true);

        // Effectuer une opération de génération de valeur mise en cache
        $result = generate_cache_value();

        // Cache de stockage
        apcu_store($cache_key, $result);

        // Retirez l'indicateur d'état de calcul
        apcu_delete($status_key);
    } else {
        // Attendez les autres demandes pour compléter l'opération de cache
        while (!$result = apcu_fetch($cache_key)) {
            sleep(1);
        }
    }
}

De cette façon, lorsque plusieurs demandes fonctionnent sur la même clé de cache en même temps, seule la première demande générera un cache et les demandes restantes attendront la fin de la génération de cache.

4. Utiliser les transactions pour assurer la cohérence

Si vos données en cache sont très importantes et ont des exigences élevées pour la cohérence, vous pouvez envisager d'utiliser un mécanisme similaire aux transactions de base de données pour garantir la cohérence des données dans un environnement simultané. Bien que l'APC ne prenne pas directement en charge les transactions, vous pouvez utiliser des transactions de base de données ou des systèmes de mise en cache externes (tels que Redis) pour obtenir des effets similaires.