LoginSignup
2
3

More than 5 years have passed since last update.

GCP memorystoreの性能を見てみる

Posted at

memorystoreとは

  • memorystoreはGCPのredisマネージドサービスです
  • BasicとStandardの2つのサービスを提供しています。BasicはHAがない構成でStandardはHA(zone replicationとautomatic failover)構成になっています
  • 価格はデータ容量ベースで決まります
  • 現在のredisのバージョンは3.2です

性能

ワークロード

  • 1KBのデータ100万件をmemorystoreに格納します
  • データのkey値はstringで1 - 1000000の値が入ります
  • 各クライアントは1 - 1000000のkey値をランダムに選択してgetを行います
  • クライアント数を増加させていきgetのレイテンシを測定します

memorystoreの設定

  • インスタンスの容量 5GB
  • ネットワークスループット 375MB/秒
  • redisはデフォルト設定です

結果

クライアント数 平均レイテンシ(μs) 最大レイテンシ(μs)
1 350 638
10 390 918
50 507 817
100 1,270 9,530
200 2,870 9,830
400 6,620 25,253
600 10,462 30,400
800 14,708 25,786
  • redisの性能を本格的に見たのは始めてたのですが、他のディスクベースのNoSQL(HBaseとかCassandraとか)に比べると安定的に早い性能が出てる感じですね
  • 800同時接続でも数十ミリ秒のレイテンシなので、ほとんどのシステムで十分と言える性能ではないでしょうか

測定プログラム

  • 参考に測定プログラムを載せておきます。GOで書かれてます。
  • host,portは適宜書き換えてください
  • オプションは--threadでスレッド数(クライアント数)を指定、--loadでmemorystoreに測定データをロードするかどうかとなります
package main

import (
    "flag"
    "fmt"
    "math/rand"
    "os"
    "sync"
    "time"

    "github.com/gomodule/redigo/redis"
)

type Result struct {
    count int
    total int64
    max   int64
}

var rChan = make(chan Result, 10000)
var wg = new(sync.WaitGroup)

const HOST = "10.0.1.4"
const PORT = "6379"
const KEYS = 1000000

func main() {
    for i, v := range os.Args {
        fmt.Printf("args[%d] -> %s\n", i, v)
    }

    t := flag.Int("thread", 1, "thread numbers")
    p := flag.Bool("load", false, "initial load")
    flag.Parse()

    if *p {
        load()
    }

    for i := 0; i < *t; i++ {
        wg.Add(1)
        go perf()
    }

    wg.Wait()
    close(rChan)

    count := 0
    var total, max int64 = 0, 0
    for r := range rChan {
        count = count + r.count
        total = total + r.total
        if max < r.max {
            max = r.max
        }
    }

    fmt.Printf("count = %d\n", count)
    fmt.Printf("total = %d\n", total)
    fmt.Printf("avg = %f\n", float64(total)/float64(count))
    fmt.Printf("max = %d\n", max)
}

func perf() {
    redisAddr := fmt.Sprintf("%s:%s", HOST, PORT)
    fmt.Printf("redis addr: %s\n", redisAddr)

    const LOOP = 10000

    conn, err := redis.Dial("tcp", redisAddr)
    if err != nil {
        panic(err)
    }

    var start, end time.Time
    var total, max int64 = 0, 0
    for i := 0; i < LOOP; i++ {
        rand.Seed(time.Now().UnixNano())
        start = time.Now()
        r, err := redis.String(conn.Do("GET", string(rand.Intn(KEYS))))
        end = time.Now()
        if err != nil {
            panic(err)
        }
        if i%1000 == 0 {
            fmt.Printf("count: %d, out: %s\n", i, r)
        }

        t := end.Sub(start).Nanoseconds()
        total = total + t
        if max < t {
            max = t
        }

    }

    var result Result
    result.count = LOOP
    result.max = max
    result.total = total

    rChan <- result
    defer wg.Done()
}

func load() {
    const base = "d"
    const length = 1000
    var data string = ""
    for i := 0; i < length; i++ {
        data = data + base
    }

    redisAddr := fmt.Sprintf("%s:%s", HOST, PORT)
    fmt.Printf("redis addr: %s\n", redisAddr)
    conn, err := redis.Dial("tcp", redisAddr)
    if err != nil {
        panic(err)
    }

    for i := 0; i < KEYS; i++ {
        _, err := redis.String(conn.Do("SET", string(i), data))
        if err != nil {
            panic(err)
        }
    }
}
2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3