囲碁におけるマイクロサービスの構築Memcachedを用いたキャッシュ


キャッシュの使用方法とキャッシュの使い方を理解することは、マイクロサービスを構築する際に重要です.この記事では、キャッシュについての一般的な概念、memcachedについての具体的な詳細について説明します. github.com/bradfitz/gomemcache .

なぜキャッシュが必要ですか?
キャッシュの背後にあるアイデアは、新しいコンセプトでは、MicroServiceでは特に明確に我々はそれを正しく使用するように理解している概念です過度の使用を避けるために、いつ、どのように過度のキャッシュに起因する可能な欠陥に応じて反応するかを知る.
適切にキャッシュを使用すると、結果を我々のユーザーに戻って返すことができます.これらの結果の例は、データベース記録、レンダリングページまたは他の高価な計算でありえました.
一方、キャッシュが正しく使用されていない場合、それは余分なレイテンシー(memcachedのような分散データストアの場合)、メモリの不足(ローカルのインプロセスキャッシュの場合)、古い結果、またはサービスが失敗する内部エラーでさえも発生する可能性があります.
そういうわけで、何かをキャッシュすることを考える前に、以下の質問に対する明確な答えが必要です.
  • 我々はいくつかの他の方法で結果をスピードアップできますか?
  • 結果を無効にする方法を正確に知っていますか?
  • 分散キャッシングまたはインプロセスキャッシュを使用するか?賛否両論はあるか
  • それらの質問をもう少し広げましょう.

    我々はいくつかの他の方法で結果をスピードアップできますか?
    これは、キャッシュにしようとしていることに依存します.たとえば、計算について話をする場合には、事前にこれらの値を事前に計算し、永続的なストアに保存し、必要に応じてそれらの値を問い合わせることができます.
    複雑なアルゴリズムについて話しているならば、ソート結果を必要とする呼び出しではなく、アルゴリズム自体を変えることができます.
    より具体的なケースでは、CDN(Content Delivery Network)を使用して、資産を返すHTTPサービスを構築するとき、より意味があります.

    結果を無効にする方法を正確に知っていますか?
    我々がしたい最後のことをキャッシュするときに、それを無効にするときにそれらを無効にする知っている理由です.
    これを決定するときにかかる通常のルートは、時間ベースの呼出しを使用して、私たちは、午前10時に毎日計算されている値をキャッシュしていると言うことができます、私たちは、次の計算が発生する前に、時間を使用して満了値を決定することができます参照してください.
    より複雑なアーキテクチャでは、これらの変更の生産者が現在のキャッシュされた値を無効にするためにイベントを発行するイベントを使用してオンデマンドで行うことができます.
    最後に重要なことは、常にそれらの結果を無効にする方法を持つことです.

    分散キャッシングまたはインプロセスキャッシュを使用するか?賛否両論はあるかDistributed caching MicroServiceが複数のインスタンスを持っている場合には、MicroServiceが複数のインスタンスを持っている場合には良い解決策です.しかし、これはサービスを他のネットワークコールに追加することになります.
    特にmemcachedにおいて、ホットキーは本当に我々のマイクロサービスを妨げることができました.そして、memcachedされたサーバーのクラスタを使用するとき、これは起こります、そして、いくつかのキーはとても人気があります.これはネットワークトラフィックを増加させ、プロセス全体を遅くします.この問題を解決するいくつかの方法は、キャッシュされたデータを複製したり、プロセス内キャッシュを使用することです.In-process caching キャッシュを処理するもう一つの方法ですが、キャッシュされた値の性質のために、我々はどれくらいのメモリを持っているかを知っていなければなりません.したがって、どのように多くのデータを格納することができますか?しかし、我々は確かに余分なネットワークコールが発生しません知っている.

    memcachedを使用したキャッシュ
    以下の例のコードが利用可能ですon Github .
    公式によるとwebsite (強調表示)

    Memcached is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering.


    The memcached APIはとてもシンプルで強力なので、ほとんどの時間を使います. Get and Set ; これらのメソッドを使用する前に留意することは重要です[]byte , 例えば、struct型Name :
    // server.go
    type Name struct {
        NConst    string `json:"nconst"`
        Name      string `json:"name"`
        BirthYear string `json:"birthYear"`
        DeathYear string `json:"deathYear"`
    }
    
    使用する場合NConst キャッシュされたレコードのキーとして、まずencoding/gob :
    // memcached.go
    func (c *Client) SetName(n Name) error {
        var b bytes.Buffer
    
        if err := gob.NewEncoder(&b).Encode(n); err != nil {
            return err
        }
    
        return c.client.Set(&memcache.Item{
            Key:        n.NConst,
            Value:      b.Bytes(),
            Expiration: int32(time.Now().Add(25 * time.Second).Unix()),
        })
    }
    
    そして、それが存在するならば、値が変換されるところを得るとき、同様のプロセスは使用されます:
    // memcached.go
    func (c *Client) GetName(nconst string) (Name, error) {
        item, err := c.client.Get(nconst)
        if err != nil {
            return Name{}, err
        }
    
        b := bytes.NewReader(item.Value)
    
        var res Name
    
        if err := gob.NewDecoder(b).Decode(&res); err != nil {
            return Name{}, err
        }
    
        return res, nil
    }
    
    コード例では、永続的なデータベースからこれらの値を返す仮想HTTPサーバを持っています.実際の使用法は次のようになります.
    // server.go
    router.HandleFunc("/names/{id}", func(w http.ResponseWriter, r *http.Request) {
        id := mux.Vars(r)["id"]
    
        val, err := mc.GetName(id)
        if err == nil {
            renderJSON(w, &val, http.StatusOK)
            return
        }
    
        name, err := db.FindByNConst(id)
        if err != nil {
            renderJSON(w, &Error{Message: err.Error()}, http.StatusInternalServerError)
            return
        }
    
        _ = mc.SetName(name) // XXX: consider error
    
        renderJSON(w, &name, http.StatusOK)
    })
    
    ワークフローは常に同じです.
  • memcachedから値を取得します.
  • 存在しない場合は、元のデータストアに問い合わせて、memcached

  • 最後の思考
    それが我々のcostumersに結果をより速く返すことができるので、キャッシングは我々のサービスのユーザー経験を改善するすばらしい方法です.具体的にはmemcached 我々は、スケールをスケールアウトするか、または経験を理想的に保つために余分なキャッシュメカニズムを追加するときに決定するために使用量を測定する必要があります.
    キャッシュすべてのものが、なぜ知っていることを確認!