diff --git a/stress/go.mod b/stress/go.mod new file mode 100644 index 0000000..56f98aa --- /dev/null +++ b/stress/go.mod @@ -0,0 +1,9 @@ +module redis_stress_test + +go 1.20 + +require ( + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/go-redis/redis/v8 v8.11.5 // indirect +) diff --git a/stress/go.sum b/stress/go.sum new file mode 100644 index 0000000..8dfa85a --- /dev/null +++ b/stress/go.sum @@ -0,0 +1,6 @@ +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= diff --git a/stress/main.go b/stress/main.go new file mode 100644 index 0000000..e21520a --- /dev/null +++ b/stress/main.go @@ -0,0 +1,131 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + "math/rand" + "sync/atomic" + "time" + + "github.com/go-redis/redis/v8" +) + +var ( + ctx = context.Background() + qpsCount int64 + totalOps int64 +) + +// 复杂数据结构示例 +type User struct { + ID int `json:"id"` + Name string `json:"name"` + Email string `json:"email"` + CreatedAt time.Time `json:"created_at"` + Tags []string `json:"tags"` + Profile Profile `json:"profile"` +} + +type Profile struct { + Age int `json:"age"` + Location string `json:"location"` + Bio string `json:"bio"` +} + +func randomUser(id int) User { + return User{ + ID: id, + Name: fmt.Sprintf("User%d", id), + Email: fmt.Sprintf("user%d@example.com", id), + CreatedAt: time.Now(), + Tags: []string{"tag1", "tag2", "tag3"}, + Profile: Profile{ + Age: rand.Intn(50) + 20, + Location: "City" + fmt.Sprintf("%d", rand.Intn(100)), + Bio: "This is a sample bio for user.", + }, + } +} + +func main() { + rdb := redis.NewClient(&redis.Options{ + Addr: "60.205.233.184:6379", // 请根据实际情况修改 + Password: "yyd00058", + DB: 0, + }) + + // 测试连接 + _, err := rdb.Ping(ctx).Result() + if err != nil { + log.Fatalf("无法连接 Redis: %v", err) + } + fmt.Println("Redis 连接成功,开始压力测试...") + + // 启动 QPS 统计协程 + go func() { + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + for range ticker.C { + count := atomic.SwapInt64(&qpsCount, 0) + fmt.Printf("当前 QPS: %d\n", count) + } + }() + + concurrency := 100 // 并发数 + for i := 0; i < concurrency; i++ { + go func(id int) { + for { + user := randomUser(id) + key := fmt.Sprintf("user:%d:%d", id, time.Now().UnixNano()) + + // 序列化复杂结构为 JSON + data, err := json.Marshal(user) + if err != nil { + log.Printf("序列化失败: %v", err) + continue + } + + // 写入 + err = rdb.Set(ctx, key, data, 0).Err() + if err != nil { + log.Printf("写入失败: %v", err) + continue + } + atomic.AddInt64(&qpsCount, 1) + atomic.AddInt64(&totalOps, 1) + + // 读取 + val, err := rdb.Get(ctx, key).Result() + if err != nil { + log.Printf("读取失败: %v", err) + continue + } + + // 反序列化 + var u User + err = json.Unmarshal([]byte(val), &u) + if err != nil { + log.Printf("反序列化失败: %v", err) + continue + } + atomic.AddInt64(&qpsCount, 1) + atomic.AddInt64(&totalOps, 1) + + // 删除 + err = rdb.Del(ctx, key).Err() + if err != nil { + log.Printf("删除失败: %v", err) + continue + } + atomic.AddInt64(&qpsCount, 1) + atomic.AddInt64(&totalOps, 1) + } + }(i) + } + + runDuration := 30 * time.Second + time.Sleep(runDuration) + fmt.Printf("压力测试结束,总操作数: %d\n", atomic.LoadInt64(&totalOps)) +}