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;
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 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;
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()) } }
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.
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;
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()) } }
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!