Maison  >  Article  >  développement back-end  >  Comment concevoir un cache de configuration qui gère efficacement les mises à jour et les erreurs ?

Comment concevoir un cache de configuration qui gère efficacement les mises à jour et les erreurs ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-10-25 06:43:02722parcourir

How to Design a Configuration Cache That Handles Updates and Errors Gracefully?

Charger la configuration à partir de fichiers et actualiser avec de nouvelles mises à jour

Énoncé du problème :

Un code la conception implique de charger une configuration à partir de fichiers au démarrage et de l'actualiser périodiquement avec des versions plus récentes. L'objectif est d'avoir un mécanisme qui gère les exigences suivantes :

  • Accès simultané à la configuration
  • Rechargement des changements de configuration détectés
  • Accessibilité à la configuration la plus récente
  • Accès immédiat à la configuration la plus récente lors des mises à jour
  • Préservation de la configuration précédente en cas d'échec d'une mise à jour

La conception initiale utilise une carte concurrente pour stocker la configuration , mais est confronté à un problème où des erreurs lors de la mise à jour peuvent conduire à une carte vide.

Solution :

Une conception simplifiée est proposée qui répond à toutes les exigences :

CustomerConfig Structure :

Définit la configuration à mettre en cache :

type CustomerConfig struct {
    Data map[string]bool
    LoadedAt time.Time
}

loadConfig Fonction :

Charge la configuration à partir des fichiers :

func loadConfig() (*CustomerConfig, error) {
    cfg := &CustomerConfig{
        Data:     map[string]bool{},
        LoadedAt: time.Now(),
    }

    // Logic to load files and populate cfg.Data
    // If an error occurs, return it

    // If loading succeeds, return the config
    return cfg, nil
}

Structure ConfigCache :

Gère la mise en cache de la configuration :

type ConfigCache struct {
    configMu sync.RWMutex
    config   *CustomerConfig
    closeCh  chan struct{}
}

Fonction NewConfigCache :

Crée un nouveau cache de configuration :

func NewConfigCache() (*ConfigCache, error) {
    cfg, err := loadConfig()
    if err != nil {
        return nil, fmt.Errorf("loading initial config failed: %w", err)
    }

    cc := &ConfigCache{
        config:  cfg,
        closeCh: make(chan struct{}),
    }

    // Launch a goroutine to periodically check for changes and load new configs
    go cc.refresher()

    return cc, nil
}

Fonction de rafraîchissement :

Vérifie périodiquement les modifications de configuration et met à jour le cache :

func (cc *ConfigCache) refresher() {
    ticker := time.NewTicker(1 * time.Minute) // Every minute
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            // Check for changes
            changes := false // Logic to detect changes
            if !changes {
                continue // No changes, continue
            }

            // Changes! Load new config:
            cfg, err := loadConfig()
            if err != nil {
                log.Printf("Failed to load config: %v", err)
                continue // Keep the previous config
            }

            // Apply / store new config
            cc.configMu.Lock()
            cc.config = cfg
            cc.configMu.Unlock()

        case <-cc.closeCh:
            return
        }
    }
}

Fonction d'arrêt :

Arrête la goroutine de rafraîchissement :

func (cc *ConfigCache) Stop() {
    close(cc.closeCh)
}

Fonction GetConfig :

Accès à la configuration actuelle :

func (cc *ConfigCache) GetConfig() *CustomerConfig {
    cc.configMu.RLock()
    defer cc.configMu.RUnlock()
    return cc.config
}

Utilisation :

cc, err := NewConfigCache()
if err != nil {
    // Handle the error appropriately
}

// Access the configuration whenever needed:
cfg := cc.GetConfig()
// Use the configuration here

// Stop the cache refreshing when necessary:
cc.Stop()

Cette solution assure :

  • Accès simultané à la configuration
  • Rechargement sur modifications détectées
  • Accessibilité à la configuration la plus récente
  • Accessibilité immédiate lors des mises à jour
  • Préservation de la configuration précédente sur échecs de mise à jour

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn