Home  >  Article  >  Database  >  What are the methods used by Go Redis client?

What are the methods used by Go Redis client?

WBOY
WBOYforward
2023-06-03 09:01:381051browse

    Introduction

    The bottom layer of go-redis and redigo is implemented by calling the universal Do method, but

    redigo:

    • Since the input is a universal type, you must remember the parameters and return values ​​of each command, which is very unfriendly to use.

    • The parameter type is universal The type makes it impossible to check the parameter type during the compilation phase.

    • Each command requires time to record the usage method, number of parameters, etc., which is costly to use;

    go-redis:

    • Refines the functions of each redis command. We only need to remember the command and directly check the application for the interface for specific usage. , low cost of use;

    • Secondly, it unifies the data type according to the underlying type of redis, and can help check the parameter type during compilation

    • And its response is uniformly returned using the Result interface, which ensures the correctness of the return parameter type and is more user-friendly;

    Performance comparison

    BenchmarkRedis/redigo_client_Benchmark-12     31406	     36919 ns/op
    BenchmarkRedis/go-redis_client_Benchmark-12   29977	     38152 ns/op
    BenchmarkRedis/redigo_client_Benchmark-12     27928	     39923 ns/op
    BenchmarkRedis/go-redis_client_Benchmark-12   27127	     46451 ns/op

    You can see from the picture above It can be seen that although each operation of go-redis is about 10% slower than redigo, redigo needs to display the application/closing connection, so the overall performance difference between the two is not big

    Redigo library

    redigo is the Go client of the Redis database. Operating Redis is basically the same as commands. Redigo commands are basically implemented through the Do method.

    Do(ctx context.Context, cmd string, args ...interface{}) (interface{}, error)

    Although calling the Do function universal parameters can Realizes all functions, but it is very unfriendly to use. The parameter type is a universal type, so the parameter type cannot be checked during the compilation stage. Secondly, each command requires time to record the usage method, number of parameters, etc., which makes the use cost high;

    Demonstration

    Demonstrates basic connection pool establishment, ping, string operation, hash operation, list operation, expire and other operations

    package main
    import (
       "fmt"
       "github.com/gomodule/redigo/redis"
    )
    func main() {
       // 新建一个连接池
       var pool *redis.Pool
       pool = &redis.Pool{
          MaxIdle:     10,  //最初的连接数量
          MaxActive:   0,   //连接池最大连接数量,(0表示自动定义),按需分配
          IdleTimeout: 300, //连接关闭时间 300秒 (300秒不使用自动关闭)
          Dial: func() (redis.Conn, error) { //要连接的redis数据库
             return redis.Dial("tcp", "localhost:6379")
          },
       }
       conn := pool.Get() //从连接池,取一个链接
       defer conn.Close()
       // 0. ping正常返回pong, 异常res is nil, err not nil
       res, err := conn.Do("ping")
       fmt.Printf("ping res=%v\n", res)
       if err != nil {
          fmt.Printf("ping err=%v\n", err.Error())
       }
       // string操作
       // set
       res, err = conn.Do("set", "name", "测试001")
       fmt.Printf("set res=%v\n", res)
       if err != nil {
          fmt.Printf("set err=%v\n", err.Error())
       }
       // get
       res, err = redis.String(conn.Do("get", "name"))
       fmt.Printf("get res=%v\n", res)
       if err != nil {
          fmt.Printf("get err=%v\n", err.Error())
       }
       // MSet   MGet
       res, err = conn.Do("MSet", "name", "测试001", "age", 18)
       fmt.Printf("MSet res=%v\n", res)
       if err != nil {
          fmt.Printf("MSet err=%v\n", err.Error())
       }
       r, err := redis.Strings(conn.Do("MGet", "name", "age"))
       fmt.Printf("MGet res=%v\n", r)
       if err != nil {
          fmt.Printf("MGet err=%v\n", err.Error())
       }
       // expire
       res, err = conn.Do("expire", "name", 5)
       fmt.Printf("expire res=%v\n", r)
       if err != nil {
          fmt.Printf("expire err=%v\n", err.Error())
       }
       // list操作
       // lpush lpop
       res, err = conn.Do("lpush", "hobby", "篮球", "足球", "乒乓球")
       fmt.Printf("lpush res=%v\n", r)
       if err != nil {
          fmt.Printf("lpush err=%v\n", err.Error())
       }
       // lpop
       rs, er := conn.Do("lpop", "hobby")
       fmt.Printf("lpop res=%v\n", rs)
       if er != nil {
          fmt.Printf("lpop err=%v\n", er.Error())
       }
       // hash 操作
       // hset
       res, err = conn.Do("HSet", "userinfo", "name", "lqz")
       fmt.Printf("HSet res=%v\n", r)
       if err != nil {
          fmt.Printf("HSet err=%v\n", err.Error())
       }
       // hget
       r4, er4 := conn.Do("HGet", "userinfo", "name")
       fmt.Printf("HGet res=%v\n", r4)
       if er4 != nil {
          fmt.Printf("HGet err=%v\n", er4.Error())
       }
    }

    Introduction and use of go-redis component

    go-redis provides three client modes corresponding to the server, cluster, sentinel, and stand-alone mode. The three modes are common in the connection pool, and also provide a flexible Hook mechanism. The underlying actual It is also the universal Do method called.

    What are the methods used by Go Redis client?

    But go-redis refines the functions of each redis command. We only need to remember the command and check the specific usage directly. Just apply for the interface, and the cost of use is low; secondly, it unifies the data type according to the underlying type of redis, which can help check the parameter type during compilation, and its response is uniformly returned using the Result interface, ensuring that the return parameter type is correct Correctness, more user-friendly;

    Demonstration

    Demonstrates basic connection pool establishment, ping, string operations, hash operations, list operations, expire and other operations

    func main() {
       var rdb = redis2.NewClient(
          &redis2.Options{
             Addr:     "localhost:6379",
             Password: "", DB: 1,
             MinIdleConns: 1,
             PoolSize:     1000,
          })
       ctx := context.Background()
       res, err = rdb.Ping(ctx).Result()
       fmt.Printf("ping res=%v\n", res)
       if err != nil {
          fmt.Printf("ping err=%v\n", err.Error())
       }
       // string操作
       // set
       res, err = rdb.Set(ctx, "name", "测试001", 0).Result()
       fmt.Printf("set res=%v\n", res)
       if err != nil {
          fmt.Printf("set err=%v\n", err.Error())
       }
       // get
       res, err = rdb.Get(ctx, "name").Result()
       fmt.Printf("get res=%v\n", res)
       if err != nil {
          fmt.Printf("get err=%v\n", err.Error())
       }
       // MSet   MGet
       res, err = rdb.MSet(ctx, "name", "测试001", "age", "18").Result()
       fmt.Printf("MSet res=%v\n", res)
       if err != nil {
          fmt.Printf("MSet err=%v\n", err.Error())
       }
       var ret []interface{}
       ret, err = rdb.MGet(ctx, "name", "age").Result()
       fmt.Printf("MGet res=%v\n", ret)
       if err != nil {
          fmt.Printf("MGet err=%v\n", err.Error())
       }
       // expire
       res, err = rdb.Expire(ctx, "name", time.Second).Result()
       fmt.Printf("expire res=%v\n", res)
       if err != nil {
          fmt.Printf("expire err=%v\n", err.Error())
       }
       // list操作
       // lpush lpop
       res, err = rdb.LPush(ctx, "hobby", "篮球", "足球", "乒乓球").Result()
       fmt.Printf("lpush res=%v\n", res)
       if err != nil {
          fmt.Printf("lpush err=%v\n", err.Error())
       }
       // lpop
       rs, err = rdb.LPop(ctx, "hobby").Result()
       fmt.Printf("lpop res=%v\n", rs)
       if er != nil {
          fmt.Printf("lpop err=%v\n", er.Error())
       }
       // hash 操作
       // hset
       res, err = rdb.HSet(ctx, "userinfo", "name", "lqz").Result()
       fmt.Printf("HSet res=%v\n", r)
       if err != nil {
          fmt.Printf("HSet err=%v\n", err.Error())
       }
       // hget
       r4, er4 = rdb.HGet(ctx, "userinfo", "name").Result()
       fmt.Printf("HGet res=%v\n", r4)
       if er4 != nil {
          fmt.Printf("HGet err=%v\n", er4.Error())
       }
    }

    Performance Test

    package main
    import (
       "context"
       redis2 "github.com/go-redis/redis/v8"
       "github.com/gomodule/redigo/redis"
       "testing"
       "time"
    )
    func BenchmarkRedis(b *testing.B) {
       // 新建一个连接池
       var pool *redis.Pool
       pool = &redis.Pool{
          MaxIdle:     10,   //最初的连接数量
          MaxActive:   1000, //连接池最大连接数量,(0表示自动定义),按需分配
          IdleTimeout: 300,  //连接关闭时间 300秒 (300秒不使用自动关闭)
          Dial: func() (redis.Conn, error) { //要连接的redis数据库
             return redis.Dial("tcp", "localhost:6379")
          },
       }
       var rdb = redis2.NewClient(
          &redis2.Options{
             Addr:         "localhost:6379",
             Password:     "",
             MinIdleConns: 10,
             PoolSize:     1000,
          })
       b.Run("redigo client Benchmark", func(b *testing.B) {
    		for j := 0; j < b.N; j++ {
    			conn := pool.Get() //从连接池,取一个链接
    			conn.Do("set", time.Now().String(), 10000, time.Second)
    			conn.Do("get", time.Now().String())
    			conn.Close()
    		}
    	})
    	ctx := context.Background()
    	b.Run("go-redis client Benchmark", func(b *testing.B) {
    		for j := 0; j < b.N; j++ {
    			rdb.Set(ctx,  time.Now().String(), 1000, time.Second)
    			rdb.Get(ctx,  time.Now().String())
    		}
    	})
    }

    Result output

    goos: darwin
    goarch: amd64
    cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    BenchmarkRedis
    BenchmarkRedis/redigo_client_Benchmark
    BenchmarkRedis/redigo_client_Benchmark-12             26386     39110 ns/op
    BenchmarkRedis/go-redis_client_Benchmark
    BenchmarkRedis/go-redis_client_Benchmark -12 28186 37794 ns/op

    The above is the detailed content of What are the methods used by Go Redis client?. For more information, please follow other related articles on the PHP Chinese website!

    Statement:
    This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete