首頁  >  文章  >  後端開發  >  如何設計一個能夠優雅地處理更新和錯誤的配置快取?

如何設計一個能夠優雅地處理更新和錯誤的配置快取?

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-10-25 06:43:02722瀏覽

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

從文件加載配置並使用新更新刷新

問題陳述:

代碼設計涉及在啟動時從文件加載配置並定期使用新版本刷新它。目標是建立一種處理以下要求的機制:

  • 對配置的並發訪問
  • 重新加載檢測到的配置更改
  • 對最新配置的可訪問性
  • 更新期間立即存取最新配置
  • 更新失敗時保留以前的配置

初始設計利用並發映射來存儲配置,但面臨更新過程中的錯誤可能導致地圖為空的問題。

解決方案:

提出了一個簡化的設計來滿足所有要求:

CustomerConfig 結構:

定義要快取的設定:

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

loadConfig 函數:

載入檔案中的設定:

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
}

載入檔案中的設定:

> >ConfigCache 結構:
type ConfigCache struct {
    configMu sync.RWMutex
    config   *CustomerConfig
    closeCh  chan struct{}
}

管理設定快取:

NewConfigCache 函數:
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
}

刷新功能:

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
        }
    }
}

定期檢查配置更改並更新緩存:

停止函數:

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

停止複習goroutine:

GetConfig 函數:

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

訪問當前配置:

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()
用法:

  • 此解決方案確保:
  • 並發存取設定
  • 偵測到變更時重新載入
  • 可存取最新設定
  • 更新期間可立即存取
更新失敗時保留先前的設定

以上是如何設計一個能夠優雅地處理更新和錯誤的配置快取?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn