【问题标题】:Go Redis Loading去 Redis 加载
【发布时间】:2015-01-16 00:31:26
【问题描述】:

我正在尝试将 2 亿个密钥加载到 redis 中,并且通常在大约 3100 万个密钥处开始出现错误并且不得不停止。我正在使用 golang 和 redis 库“github.com/garyburd/redigo/redis”

我是这样设置连接池的:

func newPool(server string) *redis.Pool {
    return &redis.Pool{
        MaxIdle: 3,
        MaxActive: 10,
        IdleTimeout: 240 * time.Second,
        Dial: func () (redis.Conn, error) {
            c, err := redis.Dial("tcp", server)
            if err != nil {
                return nil, err
            }
            return c, err
        },
        TestOnBorrow: func(c redis.Conn, t time.Time) error {
            _, err := c.Do("PING")
            return err
        },
    }
}

然后我尝试用这个函数填充 redis:

func RedisServerBatchLoadKeys(rtbExchange string, keys []string){
  redisLock.Lock()
  defer redisLock.Unlock()
  retry := 0
  for {
    conn := GetConnOrPanic(rtbExchange)
    defer conn.Close()
    conn.Send("MULTI")
    for _, key := range keys {
      conn.Send("SET", key, maxCount)
      conn.Send("EXPIRE", key, numSecondsExpire)
    }
    _, err := conn.Do("EXEC")
    if err == nil {
      break
    } else if !(err == io.EOF) {
      CheckRedisError(err, rtbExchange, "Could not load batch")
    } else {
      retry ++
    }
    if retry >= 10 {
      CheckRedisError(err, rtbExchange, "Could not load batch - 10 retries")
    }
  }
}

我遇到了很多错误,例如:

  • 读取 tcp 10.249.15.194:6379:对等方重置连接
  • 拨号 tcp 10.249.15.194:6379:连接被拒绝
  • redis#RedisError : EOF

我是在做一些根本错误的事情,还是我必须添加更多错误检查(除了我添加的 EOF)。

谢谢,

【问题讨论】:

  • 我不知道GetConnOrPanic() 是做什么的,但是您是否想在一次交易中设置数百万个值?将每个 SET/EXPIRE 放入单个 MULTI/EXEC 事务中。
  • 抱歉,我一次设置了 100 个
  • 您似乎在每次迭代时都从池中获得了一个新连接,而没有关闭它。 defer 只在函数退出时关闭它。
  • 我建议删除外部重试循环。如果应用程序未能设置密钥,则说明出现问题。重试可能会掩盖问题。使用 SETEX 使用单个命令设置密钥和过期时间。检查您在单个事务中设置的密钥数量。在事务中设置一百万个密钥将失败。您能否展示 GetConnOrPanic 的代码或解释它的作用?

标签: go redis


【解决方案1】:

只是猜测:2 亿个密钥是很多。你有足够的内存来存储这么大的数据库吗?

Redis 文档说:

Redis 最多可以处理 2^32 个键,并且经过实践测试,每个实例至少可以处理 2.5 亿个键。

换句话说,您的限制可能是系统中的可用内存。

他们还说:

如果 Redis 内存不足会怎样?

Redis 要么被 Linux 内核 OOM 杀手杀死,要么因错误而崩溃,要么开始变慢。

在我看来,您无法连接,因为服务器实际上已关闭,这似乎是合理的。也许它会重新启动,并且下次运行脚本时,它每次都会到达同一个地方,因为那是你内存不足的时候。

如果这是您的问题,您可以尝试以下方法:

  1. 使用可以更有效地存储数据的 redis 哈希。见http://redis.io/topics/memory-optimization
  2. 跨多个服务器对数据集进行分区(分片)(例如,如果您有 4 个服务器,您可以使用 key % 4 来确定要存储在哪个 redis 服务器下)如果您的目标是 O(1) 查找尽管由于存在多个故障点而使系统变得更脆弱,但您仍然会得到它。

【讨论】:

  • 我最终发现我们的 redis 服务器内存不足。谢谢您的帮助。打算转向 redis 哈希。
猜你喜欢
  • 2017-04-23
  • 1970-01-01
  • 2020-11-10
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多