3

使用Redis和Go实现高性能缓存

 8 months ago
source link: https://www.jdon.com/71815.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

使用Redis和Go实现高性能缓存 - 极道

Go 是构建高性能 Web 应用程序的优秀语言,而高性能 Web 应用程序通常需要集中式缓存

当今流行的 Go 库缺乏对内存高效流的支持。相反,他们提供了[]byte方式,如果您缓存小对象,这不是问题,但如果您缓存大于 1kb 的对象,则[]byte则慢了。

/ This code uses https://github.com/redis/go-redis, but the same
// restrictions apply with Rueidis and Redigo.
func redisHandler(w http.ResponseWriter, r *http.Request) {
    ctx := context.Background()

// Extract key from RequestURI
    key := strings.TrimLeft(r.RequestURI, "/")

//以字节片形式从 Redis 获取值
    val, err := rdb.Get(ctx, key).Bytes()
    if err == redis.Nil {
        http.Error(w, "Key not found in Redis", http.StatusNotFound)
        return
    } else if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

_, err = w.Write(val)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

流式读取简介
Redis 协议并不妨碍我们构建流 API。因此,我编写了redjet,一个面向性能的 Redis 库。

使用redjet,您可以像这样编写代码:

func redisHandler(w http.ResponseWriter, r *http.Request) {
    ctx := context.Background()

// 从 RequestURI 中提取键值
    key := strings.TrimLeft(r.RequestURI, "/")

//将值直接从 Redis 流式传输到响应。
    _, err := rdb.Command("GET", key).WriteTo(w)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

流式写入
流行的 Redis 库在向 Redis 写入值时也遇到同样的问题。[]byte它们要求您在通过网络发送之前将整个值保存在内存中。

使用redjet,您可以将值流式传输到 Redis,如下所示:

fi := strings.NewReader("Some file contents")

err := rdb.Command("SET", "key", fi).Ok()
// handle error

有一个重要的警告。在 Redis 协议中,值是有长度前缀的,所以我们不能流式传输 vanilla io.Reader。我推测这是流行库不支持流写入的主要原因。

为了解决这个问题,redjet需要将其redjet.LenReader定义为:

type LenReader interface {
    Len() int
    io.Reader
}

可使用 redjet.NewLenReader 快速创建。

标准库中的某些类型(例如 bytes.Readerstrings.Readerbytes.Buffer)可以方便地隐式实现redjet.LenReader.

性能测试
对 redjet 进行了基准测试:

完整的基准测试结果可在此处获取

divisor:快速且易于配置的负载均衡器

用Go语言提供快速且易于配置的负载均衡器。目前它包括round-robin、weighted round-robin、least-connection、ip-h.

Go运行时的两个主要限制

Go 的并发运行时在云应用程序中可以很好地扩展。大多数 Go 应用程序容器都会在 Kubernetes 集群上的某个地方发出 CPU 请求,消耗几个 vCPU .

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK