キャッシュリクエスト実行結果

GolangBeginner
オンラインで実践に進む

はじめに

このプロジェクトでは、Go のsingleflightパッケージを基にした期限切れ時間をサポートするキャッシングライブラリを実装する方法を学びます。このキャッシングライブラリは、分散システムでリクエストの実行結果をキャッシュするために使用でき、アプリケーションのパフォーマンスを向上させます。

👀 プレビュー

$ /usr/local/go/bin/go test --race
PASS
ok      cacheflight     1.263s

🎯 タスク

このプロジェクトでは、以下を学びます。

  • Go モジュールを初期化し、必要なパッケージをインストールする方法
  • singleflightパッケージを使用してキャッシングライブラリを実装する方法
  • キャッシングライブラリをテストして、期待通りに機能することを確認する方法

🏆 成果

このプロジェクトを完了すると、以下のことができるようになります。

  • キャッシングの基本概念と Go のsingleflightパッケージを理解する
  • 期限切れ時間をサポートするキャッシングライブラリを実装する
  • キャッシングライブラリを分散システムに統合して、アプリケーションのパフォーマンスを向上させる

モジュールを初期化して必要なパッケージをインストールする

このステップでは、モジュールを初期化し、プロジェクトに必要なパッケージをインストールする方法を学びます。

  1. /home/labex/project ディレクトリでターミナルを開きます。

  2. 以下のコマンドを使用してモジュールを初期化します。

    /usr/local/go/bin/go mod init cacheflight
    
  3. 以下のコマンドを使用して必要なパッケージをインストールします。

    /usr/local/go/bin/go get github.com/golang/groupcache/singleflight
    /usr/local/go/bin/go get github.com/stretchr/testify/assert
    

キャッシングライブラリを実装する

このステップでは、singleflightパッケージを基にしたキャッシングライブラリを実装します。

  1. /home/labex/project ディレクトリにある cacheflight.go ファイルを開きます。

  2. import に必要な内容を追加します。

    import (
        "sync"
        "time"
    
        "github.com/golang/groupcache/singleflight"
    )
    
  3. type Grouptype cacheResult に必要な内容を追加します。

    // cacheResult はキャッシュ結果です
    type cacheResult struct {
        data      interface{} // キャッシュデータ
        ctime     time.Time   // キャッシュ作成日時
        isRunning chan bool   // 関数が実行中かどうか
    }
    
    // Group はコア構造体です
    type Group struct {
        cacheExpiration time.Duration          // キャッシュの有効期限
        sfg             *singleflight.Group    // singleflight グループ
        cache           map[string]cacheResult // キャッシュ結果
        mu              sync.Mutex             // ミューテックス
    }
    
  4. NewGroup 関数を実装して、指定されたキャッシュ有効期限で新しいキャッシンググループを返します。

    func NewGroup(cacheExpiration time.Duration) (group *Group) {
        group = &Group{
            sfg:             &singleflight.Group{},
            cache:           make(map[string]cacheResult),
            cacheExpiration: cacheExpiration,
        }
        return
    }
    
  5. do 関数を実装して、キャッシングロジックを処理します。

    func (g *Group) do(key string, fn func() (interface{}, error)) (ret interface{}, err error) {
        return g.sfg.Do(key, func() (interface{}, error) {
            g.mu.Lock()
            result, ok := g.cache[key]
            if result.isRunning!= nil {
                g.mu.Unlock()
                // fnが完了するまで待つ
                <-result.isRunning
                return g.do(key, fn)
            } else if!ok || result.ctime.Add(g.cacheExpiration).Before(time.Now()) {
                // キャッシュが存在しないか、期限切れの場合
                var run = make(chan bool)
                result.isRunning = run
                g.cache[key] = result
                // fnが完了してrunチャネルをクローズしたとき、他のgoroutineがキャッシュを取得できるようにする
                defer close(run)
            } else {
                // キャッシュが存在し、期限切れでない場合
                g.mu.Unlock()
                return result.data, nil
            }
    
            g.mu.Unlock()
    
            // 異なるキーは同時に実行できる
            ret, err = fn()
            if err!= nil {
                return ret, nil
            }
    
            result = cacheResult{
                data:  ret,
                ctime: time.Now(),
            }
            g.mu.Lock()
            g.cache[key] = result
            g.mu.Unlock()
    
            return ret, nil
        })
    }
    
  6. Do 関数を実装して、do 関数のラッパーとします。

    func (g *Group) Do(key string, fn func() (interface{}, error)) (ret interface{}, err error) {
        return g.do(key, fn)
    }
    

キャッシングライブラリをテストする

このステップでは、キャッシングライブラリが期待通りに機能することを確認するために、それをテストします。

  1. /home/labex/project ディレクトリでターミナルを開きます。

  2. 以下のコマンドを実行してテストを実行します。

    cd /home/labex/project
    /usr/local/go/bin/go test --race
    
  3. キャッシュ関数が正しく実装されている場合、以下の出力が表示されます。

    PASS
    ok      cacheflight     1.263s
    
  4. タイムアウトエラーに遭遇した場合は、ターミナルで以下のコマンドを実行し、その後再検査ボタンをクリックしてチェックを通過させます。

    cd /home/labex/project
    /usr/local/go/bin/go test --race
    

おめでとうございます!singleflightパッケージを基にしたキャッシングライブラリを正常に実装しました。これで、分散システムでこのライブラリを使用してリクエストの実行結果をキャッシュし、アプリケーションのパフォーマンスを向上させることができます。

まとめ

おめでとうございます!このプロジェクトを完了しました。LabEx でさらに多くの実験を行って、スキルを向上させることができます。

✨ 解答を確認して練習✨ 解答を確認して練習✨ 解答を確認して練習