Redis

1. simple example

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/go-redis/redis/v8"
)

func main() {
    // 创建Redis客户端
    client := redis.NewClient(&redis.Options{
        Addr:     "dbconn.sealosbja.site:43360", // Redis服务器地址
        Username: "",
        Password: "", // 密码,如果没有密码则为空字符串
        DB:       0,          // 使用的数据库编号
    })

    ctx := context.Background()
    // Ping测试连接
    pong, err := client.Ping(ctx).Result()
    if err != nil {
        log.Fatal("Could not connect to Redis: ", err)
    }
    fmt.Println(pong, err)

    // 设置键值对
    err = client.Set(ctx, "key", "value", 0).Err()
    if err != nil {
        fmt.Println(err)
    }

    // 获取键值对
    val, err := client.Get(ctx, "key").Result()
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println("key:", val)
}

2. redis pool

package main

import (
    "fmt"
    "time"

    redigo "github.com/gomodule/redigo/redis"
)

func main() {
    var addr = "dbconn.sealosbja.site:43360"
    var username = "default"
    var password = "7jkmb4jk"

    pool := PoolInitRedis(addr, username, password)
    // 返回值为activeConn类型,有三个属性,第一个属性为连接池指针对象,第二个属性为连接指针对象,第二个为state表示连接状态
    /**
    * type activeConn struct {
    *    p     *Pool
    *    pc    *poolConn
    *    state int
    *}
    **/
    c1 := pool.Get()
    c2 := pool.Get()
    c3 := pool.Get()
    c4 := pool.Get()
    // 超过MacActive,Wait参数为false,获取的连接失败;true会阻塞等待
    c5 := pool.Get()
    // &{0xc00012c500 0xc00015c460 0} &{0xc00012c500 0xc0002220a0 0} &{0xc00012c500 0xc0000be320 0} &{0xc00012c500 0xc00015c780 0} {0x801900}
    fmt.Println(c1, c2, c3, c4, c5)
    fmt.Println(pool.ActiveCount()) // 4

    c1.Close()
    c2.Close()
    c3.Close() // 超过MaxIdle的连接,在被释放的时候会被自动关闭
    c4.Close()
    c5.Close()

    // &{0xc00012c500 <nil> 0} &{0xc00012c500 <nil> 0} &{0xc00012c500 <nil> 0} &{0xc00012c500 <nil> 0} {0x801900}
    fmt.Println(c1, c2, c3, c4, c5)
    fmt.Println(pool.ActiveCount()) // 2

    // 未超过idleTimeou,可以复用两个连接,再新建两个连接
    time.Sleep(time.Second * 3)
    c1 = pool.Get()
    c2 = pool.Get()
    c3 = pool.Get()
    c4 = pool.Get()
    c5 = pool.Get()
    // &{0xc00012c500 0xc00015c780 0} &{0xc00012c500 0xc0000be320 0} &{0xc00012c500 0xc000222370 0} &{0xc00012c500 0xc0002225a0 0} {0x801900}
    // 0xc00015c780 0xc0000be320为复用连接,其余2个为新建连接
    fmt.Println(c1, c2, c3, c4, c5)
    fmt.Println(pool.ActiveCount()) // 4

    c1.Close()
    c2.Close()
    c3.Close() // 超过MaxIdle的连接,在被释放的时候会被自动关闭
    c4.Close()
    c5.Close()

    // 超过idleTimeou,两个idle的连接中Get的时候被释放;这里的所有四个连接都是新的tcp连接
    time.Sleep(10 * time.Second)
    c1 = pool.Get()
    c2 = pool.Get()
    c3 = pool.Get()
    c4 = pool.Get()
    c5 = pool.Get()
    // &{0xc00012c500 0xc000222690 0} &{0xc00012c500 0xc0000be820 0} &{0xc00012c500 0xc0000bea50 0} &{0xc00012c500 0xc0000bebe0 0} {0x801900}
    fmt.Println(c1, c2, c3, c4, c5)
    fmt.Println(pool.ActiveCount()) // 4

    c1.Close()
    c2.Close()
    c3.Close() // 超过MaxIdle的连接,在被释放的时候会被自动关闭
    c4.Close()
    c5.Close()

    time.Sleep(time.Second * 10)
    b1 := pool.Get()
    b2 := pool.Get()
    b3 := pool.Get()

    // 超过idleTimeout,所有连接都新建,redis一共有3个连接
    // &{0xc00012c500 0xc00015ceb0 0} &{0xc00012c500 0xc000222a50 0} &{0xc00012c500 0xc00015d1d0 0}
    fmt.Println(b1, b2, b3)
    fmt.Println(pool.IdleCount())   // 0
    fmt.Println(pool.ActiveCount()) // 3
    time.Sleep(time.Second * 5)
    pool.Close()
}

// redis pool
func PoolInitRedis(server, username, password string) *redigo.Pool {
    return &redigo.Pool{
        // 最大空闲连接数;没有redis操作时依然可以保持这个连接数量,但要在IdleTimeout的时间范围内,不然就会关闭.
        // 但是连接只会在从pool中重新get的时候判断并释放,如果不从连接中get是不会释放的
        MaxIdle:     2,
        IdleTimeout: 5 * time.Second, // 最大空闲时间
        MaxActive:   4,               //最大数
        //Wait:        true,            // 连接池满时,Get()会等待而不是返回错误
        Dial: func() (redigo.Conn, error) {
            c, err := redigo.Dial("tcp", server)
            if err != nil {
                return nil, err
            }
            if username != "" && password != "" {
                if _, err := c.Do("AUTH", username, password); err != nil {
                    c.Close()
                    return nil, err
                }
            }
            return c, err
        },
        TestOnBorrow: func(c redigo.Conn, t time.Time) error {
            _, err := c.Do("PING")
            return err
        },
    }
}

评论