Help us understand the problem. What is going on with this article?

groupcache‎ で組み込み型分散キャッシュ

More than 5 years have passed since last update.

groupcache‎ は Go で書かれた分散キャッシュライブラリで、複数プロセスでキャッシュを共有するプログラムが簡単に書けます。多くの用途で memcached を置き換えることを目指していて、Google のプロダクション環境で使われているようです。

個人的に groupcache の魅力は、

  • キャッシュを複数のピアに分散する (sharding)
  • キャッシュに無いデータを同時に大量にリクエストしても、キャッシュ生成処理は1度だけ実行され、他のリクエストには生成されたキャッシュを返す(厳密では無いが、だいたいの場合1度きり)
  • 頻繁にリクエストされるデータがリモートにあった場合、ローカルにもキャッシュする

一方、注意しないといけない点はキャッシュのアップデートには対応していないことです。groupcache には expire や明示的な破棄は存在しません。あるキーに対する値は 常に同じ であることが要求されます。

サンプル

サンプルコードがほとんどなくて、groupcache の使い方が分かりにくかったのでサンプルを貼っておきます。このサンプルではピアと通信するのに http を使いますが、フロントとはポートを分けておきたかったので martini とは別で動かしています。

package main

import (
    "encoding/json"
    "github.com/codegangsta/martini"
    "github.com/golang/groupcache"
    "net/http"
    "os"
    "time"
)

func main() {
    addr := os.Getenv("GROUPCACHE_ADDR")
    peers := groupcache.NewHTTPPool("http://" + addr)
    peers.Set("http://127.0.0.1:8000", "http://127.0.0.1:8001")
    go http.ListenAndServe(addr, peers)
    heavy := groupcache.NewGroup("heavy", 64<<20, groupcache.GetterFunc(heavyTask))

    m := martini.Classic()
    m.Get("/_stats", func() []byte {
        v, err := json.Marshal(&heavy.Stats)
        if err != nil {
            panic(err)
        }
        return v
    })
    m.Get("/:key", func(params martini.Params) string {
        var result string
        if err := heavy.Get(nil, params["key"], groupcache.StringSink(&result)); err != nil {
            panic(err)
        }
        return result
    })
    m.Run()
}

func heavyTask(ctx groupcache.Context, key string, dst groupcache.Sink) error {
    time.Sleep(400 * time.Millisecond)
    dst.SetString("Value of " + key)
    return nil
}

実行

上記のコードを main.go というファイル名で保存したら、端末を2つ開いて以下のように実行します。

$ GROUPCACHE_ADDR=127.0.0.1:8000 go run main.go
$ GROUPCACHE_ADDR=127.0.0.1:8001 PORT=3001 go run main.go

3つ目を開いて curl で試すと、キャッシュされているのが分かると思います。

$ curl localhost:3000/foo  # 400ms
$ curl localhost:3001/foo  # <1ms

また、http://localhost:3000/_stats にアクセスすると統計情報が JSON で取れます。

課題

groupcache にはピアの自動更新機能はありません。そのため、うまく使うにはピアの管理がポイントになります。

orchestration ツールと組み合わせるか、memberlistetcd と組み合わせて使うとよさそうです。

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした