GO中调用redis时,当并发量比较大时出现的问题。

yuyifeichina · 2017-06-08 09:18:03 · 10345 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2017-06-08 09:18:03 的主题,其中的信息可能已经有所发展或是发生改变。

GO中调用redis时,实始化一个连接池,做法也是一般的用户:

&redis.Pool{
    MaxIdle:     beego.AppConfig.DefaultInt("redis::maxidle", 1),
    MaxActive:   beego.AppConfig.DefaultInt("redis::maxactive", 10),
    IdleTimeout: time.Duration(beego.AppConfig.DefaultInt64("redis::idle_time_out", 180)) * time.Second,

    Dial: func() (redis.Conn, error) {
        log.Println("func dial REDIS_HOST:" + REDIS_HOST)
        c, err := redis.Dial("tcp", REDIS_HOST)
        if err != nil {
            log.Println("dial error:", err)
            return nil, err
        }

        // 选择db
        c.Do("SELECT", REDIS_DB)
        return c, nil
    },
}

类似于以上,MaxActive曾调为100,或几K,大小,当一秒请求数据量,达到5000次以上时,每一次都调用:

func GetValue(UID int) (value map[string]string, err error) {
    // 获取连接
    rs := RedisClient.Get()
    defer rs.Close()


    value, err = redis.StringMap(rs.Do("HGETALL", "xxxxx:"+strconv.Itoa(UID)))
    if err != nil {
        log.Println(err)
    }

    return value, err
}

这样的一个接口时,会导致CPU达到100%以上,同时出现redigo: connection pool exhausted这样的错误,发现是不断地调用Dial: func() (redis.Conn, error),他不是有连接池吧为什么要不断地调用DIAL?,一般这样大量数据请求时,做法如何?


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

10345 次点击  
加入收藏 微博
10 回复  |  直到 2018-06-04 13:40:34
blov
blov · #1 · 8年之前

业务访问量不小啊。按理不会出现这样的情况,向 https://github.com/garyburd/redigo 作者反馈看看!

monky
monky · #2 · 8年之前

redigo有连接池没错,但是需要自行获取和释放连接 参考我之前的文章 http://www.jianshu.com/p/85cff688d02b

luominggao123
luominggao123 · #3 · 8年之前

可以做一个锁机制去处理?

a454213722
a454213722 · #4 · 8年之前

每次运行程序是不是都用连接池连接了一下redis

lys861205
lys861205 · #5 · 8年之前

在创建连接池的时候,需要把结构Pool中的Wait设置为true,表示等待 Wait 默认为false,为false时,表示如果连接池使用完,不需要等待连接释放,直接返回“redigo: connection pool exhausted”错误, Wait 为true时,如果连接池使用完,需要等待归还连接池,返回可用的连接对象。

marlonche
marlonche · #6 · 8年之前

可以使用通用的连接池,比如: https://godoc.org/github.com/marlonche/connpool

lys861205
lys861205 · #7 · 8年之前

MaxIdle: beego.AppConfig.DefaultInt("redis::maxidle", 1), MaxActive: beego.AppConfig.DefaultInt("redis::maxactive", 10),

MaxIdle 表示队列中空闲连接的数量,MaxActive 表示最大激活数量, 如果同时创建10个连接,然后Close之后,只用1个会放到空闲队里中,其他9个直接会关闭TCP连接,所以会不断地调用Dial: func() (redis.Conn, error),其实连接池中,永远只用1个连接。

xiaochuan
xiaochuan · #8 · 8年之前

感觉应该是每次使用都会连接吧 。这个会爆棚的

vearne
vearne · #9 · 7年之前

connection pool exhausted 这个问题我也遇到了,解决方法可以参考这篇文章

vearne
vearne · #10 · 7年之前
vearnevearne #9 回复

connection pool exhausted 这个问题我也遇到了,解决方法可以参考这篇文章

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传