redis-benchmark命令为什么不遵循redis协议?

Pin*_*hio 1 tcp go redis

运行redis-benchmark命令后,我正在直接从tcp连接中读取数据,据我所知,我redis-benchmark没有遵循redis协议。

Redis的协议是在其网站上的声明:

RESP在Redis中用作请求-响应协议的方式如下:

  • 客户端将命令作为大容量字符串的RESP数组发送到Redis服务器。
  • 服务器根据命令实现以RESP类型之一进行回复。

这意味着正确的客户端实现必须始终发送批量字符串的RESP数组。

如果是这样,那么任何不以*开头的内容都将被视为语法错误(因为它不是RESP数组)。

因此,如果要向Redis服务器发送ping命令,则必须将其作为长度为1的resp数组发送,其中包含1个包含ping字的大容量字符串。例如:

“ * 1 \ r \ n $ 4 \ r \ nPING \ r \ n”

但是,每当我直接收听redis-benchmark命令并读取其tcp连接时,我都会得到:

“ PING \ r \ n”

这确实不是遵循redis的协议。这是bug还是redis协议中隐含着使ping变得特别的东西?据我所知,找不到ping是特殊的,长度1命令也不是特殊的内容。有人知道发生了什么吗?

要自己查看重现这些结果,您可以复制我的代码以直接检查它:

package main

import (
    "fmt"
    "log"
    "net"
)

func main() {
    RedisBenchmark()
}

func RedisBenchmark() {
    url := "127.0.0.1:6379"
    fmt.Println("listen: ", url)
    ln, err := net.Listen("tcp", url) //announces on local network
    if err != nil {
        log.Fatal(err)
    }
    for {
        conn, err := ln.Accept() //waits and returns the next connection to the listener
        if err != nil {
            log.Fatal(err)
        }

        tcpConn := conn.(*net.TCPConn)
        go HandleConnection(tcpConn)
    }
}

func HandleConnection(tcpConn *net.TCPConn) {
    b := make([]byte, 256) //TODO how much should I read at a time?
    n, err := tcpConn.Read(b)
    if err != nil {
        fmt.Println("n: ", n)
        log.Fatal(err)
    }
    fmt.Printf("+++++> raw input string(b): %q\n", string(b))
    msg := string(b[:n])
    fmt.Printf("+++++> raw input msg: %q\n", msg)
}
Run Code Online (Sandbox Code Playgroud)

并使用go来运行它:

go run main.go

然后在另一个终端(或tmux窗格)上:

redis-benchmark

对于所有测试,或者如果您只想使用1个客户端运行ping:

redis基准-c 1 -t ping -n 1

您可以在以下位置查看带有标志的运行方式的详细信息:http : //redis.io/topics/benchmarks

sov*_*ran 5

这称为内联命令。检查“ Redis协议”文章的“ 内联命令”部分。