让我们来观察一下GCP Memorystore的性能

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のレイテンシを測定します

记忆库的设定

    • インスタンスの容量 5GB

 

    • ネットワークスループット 375MB/秒

 

    redisはデフォルト設定です

最終的結果

クライアント数平均レイテンシ(μs)最大レイテンシ(μs)135063810390918505078171001,2709,5302002,8709,8304006,62025,25360010,46230,40080014,70825,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)
        }
    }
}