ホームページ >バックエンド開発 >Golang >Go でコンテキストを使用してリクエスト結果キャッシュの自動リフレッシュを実装する方法

Go でコンテキストを使用してリクエスト結果キャッシュの自動リフレッシュを実装する方法

WBOY
WBOYオリジナル
2023-07-22 11:41:251622ブラウズ

Go でコンテキストを使用してリクエスト結果キャッシュの自動更新を実装する方法

要約:
Web アプリケーション開発では、ユーザー エクスペリエンスを向上させるために、一部のリクエストの結果をキャッシュする必要がある場合があります。データベースや他のサービスへのアクセスを減らすため。しかし、キャッシュされたデータの有効期限が問題となり、キャッシュが期限切れになると期限切れのデータを取得してしまい、表示や動作が誤ってしまう可能性があります。この記事では、Go のコンテキスト パッケージを使用してリクエスト結果キャッシュの自動更新機能を実装し、キャッシュされたデータの適時性を確保する方法を検討します。

  1. コンテキスト パッケージとは
    Go 言語では、コルーチン間でコンテキスト情報を転送するためのツールとしてコンテキスト パッケージが提供されています。 context パッケージの Context タイプは、コルーチンの実行を制御およびキャンセルするためのいくつかのメソッドとプロパティを提供します。 Web リクエストを処理するとき、コンテキスト パッケージを通じてリクエストのコンテキスト情報を渡し、いくつかの関連操作の実行を制御できます。
  2. リクエスト結果のキャッシュの実装
    まず、リクエスト結果とその有効期限を保存するキャッシュ構造を定義する必要があります。コードは次のとおりです。
type CacheItem struct {
    result      interface{}
    expireAt    time.Time
}

type Cache struct {
    cacheMap    map[string]CacheItem
    mutex       sync.RWMutex
}

上記のコードでは、マップを使用してキャッシュ アイテムを保存します。キーはリクエストに関連する一意の識別子、値はキャッシュ アイテムの詳細 (結果や有効期限など)。同時実行の安全性を確保するために、ミューテックス ロックを使用します。

次に、キャッシュ データを取得する関数を作成する必要があります。この関数は、まずリクエスト結果がキャッシュに存在するかどうかを確認し、期限切れかどうかを判断します。キャッシュされた結果が存在し、有効期限が切れていない場合は、キャッシュされたデータが直接返されます。それ以外の場合は、実際のリクエストを行って結果をキャッシュする必要があります。コードは次のとおりです。

func (c *Cache) Get(key string) interface{} {
    c.mutex.RLock()
    defer c.mutex.RUnlock()

    item, ok := c.cacheMap[key]
    if ok && item.expireAt.After(time.Now()) {
        return item.result
    }

    // 发起请求并更新缓存
    result := makeRequest(key)
    c.cacheMap[key] = CacheItem{result: result, expireAt: time.Now().Add(time.Minute)}

    return result
}

上記のコードでは、同時実行の安全性を確保するために読み取りロックを使用してキャッシュ項目を読み取ります。キャッシュ項目が存在し、有効期限が切れていない場合は、キャッシュ結果が直接返されます。そうでない場合は、実際のリクエストが開始され、リクエスト結果がキャッシュに保存されます。

  1. キャッシュの更新
    キャッシュされたデータの適時性を確保するには、キャッシュを定期的に更新する必要があります。 Go では、コンテキスト パッケージの WithDeadline 関数を使用して期限を設定し、タイムアウト後に対応する操作を自動的にキャンセルできます。この機能を使用すると、キャッシュを自動的に更新できます。コードは次のとおりです:
func (c *Cache) RefreshCache(ctx context.Context, key string) {
    ticker := time.NewTicker(time.Minute)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            result := makeRequest(key)
            c.mutex.Lock()
            c.cacheMap[key] = CacheItem{result: result, expireAt: time.Now().Add(time.Minute)}
            c.mutex.Unlock()
        case <-ctx.Done():
            return
        }
    }
}

上記のコードでは、Ticker オブジェクトを使用して makeRequest 関数を定期的に呼び出し、キャッシュを更新します。同時に、select ステートメントを使用してリッスンします。コンテキストがキャンセルされた後にリフレッシュ ループを終了するためのコンテキスト キャンセル信号。

  1. 使用例
    次に、単純な Web アプリケーションを使用して、上記のキャッシュ実装の使用方法を示します。コードは次のとおりです:
package main

import (
    "context"
    "fmt"
    "net/http"
    "sync"
    "time"
)

type CacheItem struct {
    result   interface{}
    expireAt time.Time
}

type Cache struct {
    cacheMap map[string]CacheItem
    mutex    sync.RWMutex
}

func makeRequest(key string) interface{} {
    // 模拟请求耗时
    time.Sleep(time.Second)
    return fmt.Sprintf("result for %s", key)
}

func (c *Cache) Get(key string) interface{} {
    c.mutex.RLock()
    defer c.mutex.RUnlock()

    item, ok := c.cacheMap[key]
    if ok && item.expireAt.After(time.Now()) {
        return item.result
    }

    result := makeRequest(key)
    c.cacheMap[key] = CacheItem{result: result, expireAt: time.Now().Add(time.Minute)}

    return result
}

func (c *Cache) RefreshCache(ctx context.Context, key string) {
    ticker := time.NewTicker(time.Minute)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            result := makeRequest(key)
            c.mutex.Lock()
            c.cacheMap[key] = CacheItem{result: result, expireAt: time.Now().Add(time.Minute)}
            c.mutex.Unlock()
        case <-ctx.Done():
            return
        }
    }
}

func main() {
    cache := &Cache{cacheMap: make(map[string]CacheItem)}

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second*5))
        defer cancel()

        key := r.URL.Path

        result := cache.Get(key)
        fmt.Fprintf(w, "%s: %s", key, result)

        // 启动刷新缓存的协程
        go cache.RefreshCache(ctx, key)
    })

    http.ListenAndServe(":8080", nil)
}

上記のコード例では、単純な HTTP サーバーを定義しています。リクエストを受信すると、キャッシュされた Get メソッドが呼び出されてデータを取得し、クライアントに返されます。 。同時に、コンテキスト パッケージを使用して 5 秒の期限を持つコンテキストを作成し、それを RefreshCache メソッドに渡してキャッシュの更新時間を制御します。

結論:
この記事では、Go の context パッケージを使用して、リクエスト結果キャッシュの自動更新機能を実装する方法を紹介します。キャッシュ構造とミューテックスを使用して同時実行の安全性を確保し、コンテキスト パッケージの機能を使用してキャッシュを定期的に更新することで、リクエスト結果を簡単にキャッシュしてデータの適時性を確保できます。上記のコード例は単なるデモであり、実際に使用するには、特定のニーズに基づいて適切な変更と最適化が必要になる場合があります。

以上がGo でコンテキストを使用してリクエスト結果キャッシュの自動リフレッシュを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。