Dans le langage Go, les scénarios de défaillance du cache de fonctions incluent : les modifications de paramètres, les modifications de variables globales, le redéploiement de programmes et les modifications simultanées. Les stratégies de traitement comprennent : 1. Calcul paresseux (le premier appel pour effectuer des calculs et mettre en cache les résultats) ; 2. Stratégie d'expiration (vérifier régulièrement la validité des résultats mis en cache) ; 3. Mécanisme de notification (s'abonner aux événements ou aux messages pour invalider automatiquement le cache) ; ); 4. Exclure le scénario d'invalidation (modifier la logique du code ou introduire d'autres technologies). Cas pratique : Le site e-commerce utilise une fonction pour obtenir les prix des produits. Il peut utiliser une stratégie d'expiration pour vérifier régulièrement les changements de prix, et utiliser un mécanisme de verrouillage pour empêcher les modifications simultanées.
Scénarios d'échec du cache des fonctions du langage Go et stratégies de traitement
Dans le langage Go, la mise en cache des fonctions peut grandement améliorer les performances du code, mais elle n'est pas parfaite. L'invalidation du cache de fonctions est inévitable. Cet article présentera les scénarios d'invalidation courants et leurs stratégies de gestion.
Scénario d'invalidation
Stratégie de traitement
1. Calcul paresseux
Le calcul paresseux est une stratégie de calcul paresseux, qui effectue uniquement des calculs et met en cache les résultats lorsque la fonction est appelée pour la première fois. directement depuis le cache.
import "sync" var m sync.Map func Fibonacci(n int) int { if n < 2 { return n } var result int val, exists := m.Load(n) if exists { result = val.(int) } else { result = Fibonacci(n-1) + Fibonacci(n-2) m.Store(n, result) } return result }
2. Stratégie d'expiration
La stratégie d'expiration consiste à vérifier régulièrement si les résultats stockés dans le cache sont toujours valides, et à les supprimer du cache s'ils sont invalides.
import ( "sync" "time" ) type entry struct { value interface{} expiry time.Time } var cache = sync.Map{} func SetWithExpiry(key, value interface{}, expiry time.Duration) { cache.Store(key, &entry{value: value, expiry: time.Now().Add(expiry)}) } func Get(key interface{}) (interface{}, bool) { val, exists := cache.Load(key) if !exists { return nil, false } entry := val.(*entry) if entry.expiry.Before(time.Now()) { cache.Delete(key) return nil, false } return entry.value, true }
3. Le mécanisme de notification
peut automatiquement invalider le cache de fonctions en s'abonnant à des événements ou à des messages. Lorsque les données pertinentes changent, un événement ou un message est déclenché pour notifier le cache de l'invalidation.
import ( "context" "sync" ) var results = sync.Map{} var invalidations = make(chan struct{}) func Memoize(ctx context.Context, f func() (interface{}, error)) (interface{}, error) { key := f val, ok := results.Load(key) if ok { return val.(interface{}), nil } result, err := f() if err != nil { return nil, err } invalidations <- struct{}{} // 触发缓存失效 results.Store(key, result) return result, nil }
4. Éliminer les scénarios d'échec
Parfois, nous pouvons éliminer les scénarios d'échec en modifiant la logique du code ou en introduisant d'autres techniques. Par exemple, en utilisant des structures de données immuables ou un accès synchrone aux données partagées.
Cas pratique
Supposons que nous soyons sur un site e-commerce et que nous disposions d'une fonction GetProductPrice
pour obtenir le prix d'un produit. Étant donné que les prix des produits changent fréquemment, nous devons utiliser la mise en cache des fonctions pour optimiser les performances.
import ( "sync" "time" ) type product struct { ID int Price float64 } var cache = sync.Map{} // GetProductPrice 从缓存获取产品价格,如果缓存中没有,则从数据库中获取并缓存 func GetProductPrice(id int) (float64, error) { val, exists := cache.Load(id) if exists { return val.(float64), nil } product, err := getProductFromDatabase(id) if err != nil { return 0, err } cache.Store(id, product.Price) return product.Price, nil }
Étant donné que les prix des produits changent régulièrement, nous devons utiliser une politique d'expiration pour gérer le cache et vérifier régulièrement si le prix a changé.
import ( "context" "sync" "time" ) var cache = sync.Map{} var invalidations = make(chan struct{}) func GetProductPriceWithExpiry(id int) (float64, error) { ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) defer cancel() for { val, exists := cache.Load(id) if exists { entry := val.(*entry) if entry.expiry.Before(time.Now()) { cache.Delete(id) } else { return val.(float64), nil } } product, err := getProductFromDatabase(id) if err != nil { return 0, err } invalidations <- struct{}{} cache.Store(id, &entry{value: product.Price, expiry: time.Now().Add(1 * time.Minute)}) return product.Price, nil } }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!