go - 使用 Golang 减少访问 Bigtable 的时间

标签 go bigtable

我想减少在我的 Golang RestApi 上访问我的表的时间。

我有一个带有 enpoint 的 Go restAPI,它需要为请求正文中指定的每个代码访问 bigtable 数据库。我设计的关键访问是“provider|client|productCode|date|..”(以及其他 4 个参数)。

对于请求正文的每个 productCode,我都进行异步调用以读取具有指定键的行。
在我的测试中,我请求了 1000 个产品代码,在我的本地机器上获取的时间约为 800~900 毫秒。云机器上的时间约为 550~450 毫秒。

我正在使用 bigtable package访问 bigTable,我使用以下代码:

package main

import (
    "log"
    "time"

    "golang.org/x/net/context"
    "google.golang.org/cloud/bigtable"
)

func main() {
    start2 := time.Now()

    listPKs := []string{"PROV|CLI|6030|20160714|8|30301.30302|ES", "PROV|CLI|44103|20160714|8|30301.30302|ES", "PROV|CLI|1454871|20160714|8|30301.30302|ES"}

    providerRS := getBDresponse(listPKs, 50000)
    if providerRS != nil {
        ///do something
    }
    elapsed2 := time.Since(start2)
    log.Printf("Time access BT: %s", elapsed2)
}

func getBDresponse(listPKs []string, timeoutMiliseconds int) []string {

    resp := make(chan string)
    table := myClient.Client.Open(TABLE_NAME)
    //async call to BT
    for _, key := range listPKs {
        go asyncDoUniqueCall(key, resp, myContext, table)
    }
    //get all responses
    providerRS := getResponses(resp, timeoutMiliseconds, len(listPKs))
    return providerRS
}

func asyncDoUniqueCall(pk string, ch chan string, ctx *context.Context, table *bigtable.Table) {
    ch <- GetRowValue(pk, ctx, table)
}

func getResponses(resp chan string, timeoutMiliseconds int, totalNumRQ int) []string {
    var ret []string

    for j := 0; j < totalNumRQ; j++ {
        select {
        case rowResponse := <-resp: //catch the response
            if rowResponse != "" {
                ret = append(ret, rowResponse)
            }
        case <-time.After(time.Duration(timeoutMiliseconds) * time.Millisecond): // timeout control 
            return nil
        }
    }
    return ret
}

//GetRowValue open the table and get the row indexed by pk and returns the stored message 
func GetRowValue(pk string, ctx *context.Context, table *bigtable.Table) string {

    var response string

    r, err := table.ReadRow(*ctx, pk)
    if err != nil {
        return ""
    }
    if len(r) > 0 {
        row := r[COLUMN_FAMILY_NAME]
        numCol := len(row)

        response = string(row[0].Value)
    }
    return response
}

我试过了 this例子太多,时代并不好:

我使用的是 gorutines 和 chanels correctyl 吗? 我访问 BT 的方式是否正确? 也许按键设计不正确?

最佳答案

我认为问题在于您使用的是一维 chan:

resp := make(chan string) 

您应该尝试通过以下方式扩大其维度:

resp := make(chan string,len(listPKs))

那是因为如果您的异步函数在 chan 中的信息被读取之前完成,那么 chan 将被阻塞。

旁注:在不执行任何检查的情况下生成 go 例程可能是问题的根源。

我建议您实现 working queue以优化您的任务。

关于go - 使用 Golang 减少访问 Bigtable 的时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38523988/

相关文章:

mongodb - NoSQL关键字在大表中搜索

nosql - Cassandra/BigTable 数据模型 - 构建索引的最佳方法是什么?

arrays - golang 在多播 ip 上发送 json

c - "Undefined symbols for architecture x86_64:"用于在 macOS Sierra 上使用 cgo 的库

string - Golang中的Scanln不接受空格

cassandra - Cassandra 是否是一个很好的候选数据库,因为它必须每秒支持超过 100 个读/写操作?

java - 如何通过行键从Bigtable中获取所有值?

go - golang反射将结构的第一个值设置为其零值

postgresql - Postgres 中的 Go 和 IN 子句

.net - 使用 .NET 应用程序将数据从外部托管写入 GCP BigTable