手写Redis缓存系统,第二章:写一个基准测试工具, 命令行工具

客户端测试代码

1. 确保 Go 环境设置正确

确保你的 Go 环境已经安装并配置正确。你可以通过以下命令检查 Go 版本:

go version

2. 编写并保存 Go 代码

确保你的代码已经修改完毕,并且保存到 main.go 文件中。例如:

package main

import (
	"flag"
	"fmt"
	"log"
	"redis-go/tool/cache-benchmark/cacheClient"
)

func main() {
   
	server := flag.String("h", "localhost", "cache server address")
	op := flag.String("c", "get", "command, could be get/set/del")
	key := flag.String("k", "", "key")
	value := flag.String("v", "", "value")
	flag.Parse()

	if *key == "" && (*op == "get" || *op == "del") {
   
		log.Fatal("key is required for get and del commands")
	}

	client := cacheClient.New("tcp", *server)
	cmd := &cacheClient.Cmd{
   *op, *key, *value, nil}
	client.Run(cmd)
	if cmd.Error != nil {
   
		fmt.Println("error:", cmd.Error)
	} else {
   
		fmt.Println(cmd.Value)
	}
}

3. 编译代码并指定输出文件名

使用 go build 命令,并指定 -o 标志来设置输出文件的名称。将生成的文件命名为 client

go build -o client main.go

这个命令会将 main.go 编译成一个名为 client 的可执行文件。

4. 运行生成的可执行文件

使用以下命令运行生成的 client 可执行文件,并传递必要的参数:

  • 获取数据

    ./client -h localhost -c get -k mykey
    
    
  • 设置数据

    ./client -h localhost -c set -k mykey -v myvalue
    
    
  • 删除数据

    ./client -h localhost -c del -k mykey
    
    

说明

  • o client 指定了输出文件的名称为 client
  • main.go 是你编译的源文件。如果你的源代码文件名不同,请相应地修改命令。

通过这些步骤,你可以将编译生成的可执行文件命名为 client 并在你的系统上运行它。

代码讲解

  1. 导入必要的包

    import (
        "flag"
        "fmt"
        "redis-go/tool/cache-benchmark/cacheClient"
    )
    
    
    • flag: 用于解析命令行参数。
    • fmt: 用于格式化输出。
    • redis-go/tool/cache-benchmark/cacheClient: 自定义的缓存客户端包,用于与缓存服务器进行交互。
  2. 定义和解析命令行参数

    func main() {
         
        server := flag.String("h", "localhost", "cache server address")
        op := flag.String("c", "get", "command, could be get/set/del")
        key := flag.String("k", "", "key")
        value := flag.String("v", "", "value")
        flag.Parse()
    
    
    • flag.String("h", "localhost", "cache server address"): 定义 h 参数,用于指定缓存服务器的地址,默认值是 localhost
    • flag.String("c", "get", "command, could be get/set/del"): 定义 c 参数,用于指定要执行的命令(getsetdel),默认值是 get
    • flag.String("k", "", "key"): 定义 k 参数,用于指定操作的键。
    • flag.String("v", "", "value"): 定义 v 参数,用于指定操作的值,仅在 set 命令中使用。
    • flag.Parse(): 解析命令行参数。
  3. 创建客户端并运行命令

    client := cacheClient.New("tcp", *server)
    cmd := &cacheClient.Cmd{
         *op, *key, *value, nil}
    client.Run(cmd)
    
    
    • cacheClient.New("tcp", *server): 使用 TCP 协议创建一个新的缓存客户端,并指定服务器地址。
    • cmd := &cacheClient.Cmd{*op, *key, *value, nil}: 创建一个 Cmd 对象,表示要执行的缓存操作,其中 op 是操作类型(getsetdel),key 是键,value 是值(在 set 操作中使用),nil 是用于存储错误的字段。
    • client.Run(cmd): 执行缓存操作。
  4. 处理结果

    if cmd.Error != nil {
         
        fmt.Println("error:", cmd.Error)
    } else {
         
        fmt.Println(cmd.Value)
    }
    
    
    • 检查 cmd.Error 是否为 nil。如果不是 nil,则输出错误信息。
    • 如果没有错误,输出命令的结果值 cmd.Value

使用方法

  1. 编译和运行

    假设你已经将这段代码保存为 main.go 文件并编译为可执行文件 cache-benchmark,可以通过以下方式运行:

    • get 操作:

      ./cache-benchmark -h localhost -c get -k mykey
      
      

      这将连接到 localhost 上的缓存服务器,并执行 get 操作来获取键 mykey 的值。

    • set 操作:

      ./cache-benchmark -h localhost -c set -k mykey -v myvalue
      
      

      这将连接到 localhost 上的缓存服务器,并执行 set 操作来设置键 mykey 的值为 myvalue

    • del 操作:

      ./cache-benchmark -h localhost -c del -k mykey
      
      

      这将连接到 localhost 上的缓存服务器,并执行 del 操作来删除键 mykey

总结

这个命令行工具提供了一个简单的方式来测试缓存服务器的 getsetdel 操作。通过命令行参数,你可以指定操作类型、键和值,从而对缓存服务器进行不同的操作并查看结果。

细心的小伙伴就发现了,上面的代码依赖于

redis-go/tool/cache-benchmark/cacheClient

这个将在下面提到:👇


cacheClient的http部分的性能测试代码讲解

package cacheClient

import (
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

type httpClient struct {
   
	*http.Client
	server string
}

func (c *httpClient) get(key string) string {
   
	resp, e := c.Get(c.server + key)
	if e != nil {
   
		log.Println(key)
		panic(e)
	}
	if resp.StatusCode == http.StatusNotFound {
   
		return ""
	}
	if resp.StatusCode != http.StatusOK {
   
		panic(resp.Status)
	}
	b, e := ioutil.ReadAll(resp.Body)
	if e != nil {
   
		panic(e)
	}
	return string(b)
}

func (c *httpClient) set(key, value string) {
   
	req, e := http.NewRequest(http.MethodPut,
		c.server+key, strings.NewReader(value))
	if e != nil {
   
		log.Println(key)
		panic(e)
	}
	resp, e := c.Do(req)
	if e != nil {
   
		log.Println(key)
		panic(e)
	}
	if resp.StatusCode != http.StatusOK {
   
		panic(resp.Status)
	}
}

func (c *httpClient) Run(cmd *Cmd) {
   
	if cmd.Name == "get" {
   
		cmd.Value = c.get(cmd.Key)
		return
	}
	if cmd.Name == "set" {
   
		c.set(cmd.Key, cmd.Value)
		return
	}
	panic("unknown cmd name " + cmd.Name)
}

func newHTTPClient(server string) *httpClient {
   
	client := &http.Client{
   Transport: &http.Transport{
   MaxIdleConnsPerHost: 1}}
	return &httpClient{
   client, "http://" + server + ":12345/cache/"}
}

func (c *httpClient)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wade_Crab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值