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

GolangGolangBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

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

👀 プレビュー

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

🎯 タスク

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

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

🏆 成果

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

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

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/ConcurrencyGroup(["Concurrency"]) go(("Golang")) -.-> go/AdvancedTopicsGroup(["Advanced Topics"]) go(("Golang")) -.-> go/TestingandProfilingGroup(["Testing and Profiling"]) go(("Golang")) -.-> go/CommandLineandEnvironmentGroup(["Command Line and Environment"]) go/ConcurrencyGroup -.-> go/goroutines("Goroutines") go/ConcurrencyGroup -.-> go/channels("Channels") go/ConcurrencyGroup -.-> go/mutexes("Mutexes") go/AdvancedTopicsGroup -.-> go/time("Time") go/TestingandProfilingGroup -.-> go/testing_and_benchmarking("Testing and Benchmarking") go/CommandLineandEnvironmentGroup -.-> go/command_line("Command Line") subgraph Lab Skills go/goroutines -.-> lab-301256{{"キャッシュリクエスト実行結果"}} go/channels -.-> lab-301256{{"キャッシュリクエスト実行結果"}} go/mutexes -.-> lab-301256{{"キャッシュリクエスト実行結果"}} go/time -.-> lab-301256{{"キャッシュリクエスト実行結果"}} go/testing_and_benchmarking -.-> lab-301256{{"キャッシュリクエスト実行結果"}} go/command_line -.-> lab-301256{{"キャッシュリクエスト実行結果"}} end

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

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

  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でさらに多くの実験を行って、スキルを向上させることができます。