Redis实例通常使用go-lang客户端redigo来丢失缓存

时间:2015-02-09 23:35:04

标签: caching go redis

我正在为博客或在线发布网站开发api,以便为他们的内容开发推荐引擎。 由于我的api为相同的url请求返回相同的json,我决定使用Redis作为高流量网站的缓存,方法是将url作为键,将json作为值传递。我最近在go-lang开发这个API,并且一直在使用redigo与我们的Redis实例交谈。我决定构建我的系统的方法是检查客户端(博客)发送的查询的URL并在redis中搜索它。但是,如果未缓存的url响应我执行301重定向到另一个api,该api应用逻辑生成该特定URL的json响应并设置redis缓存。然而,当我测试我的Redis是否正常工作时,我意识到它比我想要的更频繁地丢失缓存。它确实缓存了映射到url的json响应,这是通过在Redis-cli中进行简单的GET确认的,但是在3-4次点击后我可以看到Redis再次丢失缓存。我仍然是一个非常新的go-lang和缓存世界所以我不确定我是否在实现中遗漏了一些东西。另外,我想知道Redis实例在什么情况下会错过缓存?它不能超时,因为Redis文档说“默认情况下,如果客户端闲置很多秒,Redis的最新版本不会关闭与客户端的连接:连接将永远保持打开状态。”所以我不确定我的设置究竟发生了什么。我的代码的相关部分如下:

package main

import (
    "flag"
    "fmt"
    "github.com/garyburd/redigo/redis"
    "log"
    "net/http"
    "time"
)

var (
    port          int
    folder        string
    pool          *redis.Pool
    redisServer   = flag.String("redisServer", "redisip:22121", "")
    redisPassword = flag.String("redisPassword", "", "")
)

func init() {
    flag.IntVar(&port, "port", 80, "HTTP Server Port")
    flag.StringVar(&folder, "folder", "www", "Serve this folder")
}

func newPool(server, password string) *redis.Pool {
    return &redis.Pool{
        MaxIdle:     3,
        MaxActive:   25000,
        IdleTimeout: 30 * 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
        },
    }
}

func main() {
    flag.Parse()
    pool = newPool(*redisServer, *redisPassword)
    httpAddr := fmt.Sprintf(":%v", port)
    log.Printf("Listening to %v", httpAddr)
    http.HandleFunc("/api", api)

    http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(folder))))
    log.Fatal(http.ListenAndServe(httpAddr, nil))

}

func api(w http.ResponseWriter, r *http.Request) {
    link := r.URL.Query().Get("url")
    fmt.Println(link)
    heading := r.URL.Query().Get("heading")
    conn := pool.Get()
    reply, err := redis.String(conn.Do("GET", link))
    defer conn.Close()
    if err != nil {
        fmt.Println("Error for link %v:%v", heading, err)
        http.Redirect(w, r, "json-producing-api", 301)
    }
    fmt.Fprint(w, reply)

}

我还必须在这里提一下,在上面的代码中,我的redis实例实际上是一个由twitter构建的twemproxy客户端,代理三个不同的端口上运行的三个不同的redis客户端。昨天一切似乎都正常,我对5k并发请求进行了成功的负载测试。但是,当我今天检查日志时,redis错过了一些查询,并被重定向到我的json-producing-api,我可以看到redigo:nil错误。我完全不确定到底出了什么问题?任何帮助将不胜感激。

编辑:根据下面的讨论,我正在详细说明用于在Redis中设置数据的代码

func SetIntoRedis(key string, value string) bool {
    // returns true if successfully set, returns false in case of an error
    conn := pool.Get()
    _, err := conn.Do("SET", key, value)
    if err != nil {

        log.Printf("Error Setting %v : %v", key, err)
        return false
    }
    return true
}

配置我的twemproxy客户端

leaf:
  listen: 0.0.0.0:22121
  hash: fnv1a_64
  distribution: ketama
  redis: true
  auto_eject_hosts: true
  server_retry_timeout: 3000
  server_failure_limit: 3
  servers:
   - 127.0.0.1:6379:1
   - 127.0.0.1:6380:1
   - 127.0.0.1:6381:1

0 个答案:

没有答案