Golang *** 作Redis

Golang *** 作Redis,第1张

Golang *** 作Redis 安装第三方开源Redis库

注意 : 命令行 *** 作不成功的直接去这个github网站里下载压缩包解压到指定目录即可

1. Set/Get 接口
package main
import (
	"fmt"
	"github.com/garyburd/redigo/redis" // 引入redis包
)
func main() {
	//通过go向redis写入数据和读取数据
	// 1. 链接到redis
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("redis.Dial err = ", err)
		return
	}

	defer conn.Close() // 关闭

	// 2、 通过go向redis写入数据 string [key - val]
	_, err = conn.Do("Set", "name", "tomjerry 狗狗")
	if err != nil {
		fmt.Println("set err = ", err)
		return
	}

	// 3.通过go向redis读取数据 string [key - val]
	r, err := redis.String(conn.Do("Get", "name"))
	if err != nil {
		fmt.Println("set err = ", err)
		return
	}

	// 返回的r的类型是interface{}
	// 因为name对应的值是string,因此我们需要转换
	// nameString := r.(string)

	fmt.Println(" *** 作 ok",  r)
}
2. *** 作Hash

说明:通过Golang对Redis *** 作 Hash数据类型

对hash数据结构,field-val 是一个一个放入和读取:

package main
import (
    "fmt"
	"github.com/garyburd/redigo/redis"
)

func main() {
	// 通过go向redis写入数据和 读取数据
	// 1.链接到redis
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("redis.Dial err = ", err)
		return
	}

	defer conn.Close()

	// 2. 通过go向redis写入数据 string [key - val]
	_, err = conn.Do("HSet", "user01", "name", "john")
	if err != nil {
		fmt.Println("hset err = ", err)
		return
	}

	_, err := conn.Do("HSet", "user01", "age", 18)
	if err != nil {
		fmt.Println("hset err = ", err)
		return
	}

	// 3.通过go向redis读取数据
	r1, err :=redis.String(conn.Do("HGet", "user01", name))
	if err != nil {
		fmt.Println("hget err = ", err)
		return
	}

	r2, err := redis.Do("HGet", "user01", "age")
	if err != nil {
		fmt.Println("hget err = ", err)
		return 
	}

	// 返回的r 是innterface{}
	// 因为name对应的值是string,因此我们需要转换
	// nameString := r.(string)

	fmt.Printf(" *** 作 OK r1 = %v r2 = %v\n", r1, r2)
}

对hash数据结构,field-val是 批量放入和读取:

package main
import (
    "fmt"
	"github.com/garyburd/redigo/redis"
)

func main() {
	conn, err := redis.Dial("tcp", "127.0.0.1:6397")
	if err != nil {
		fmt.Println("redis Dial err = ", err)
		return
	}

	_, err := conn.Do("HMSet", "user02", "name", "jack", "age", 21)
	if err != nil {
		fmt.Println("HMSet err = ", err)
		return
	}

	r, err := redis.String(conn.Do("HMGet", "user02", "name", "age"))
	if err != nil {
		fmt.Println("hmget err = ", err)
		return
	}

	for i, V := range r {
		fmt.Printf("r[%d] = %s\n", i, v)
	}
}
3. 批量Set/Get数据

说明:通过golang对redis *** 作,一次 *** 作可以Set/Get多个key-val数据

_, err := conn.Do("MSet", "name", "golang", "address", "北京")
r, err := redis.String(conn.Do("MGet", "name", "address"))

for _, v := range r {
    fmt.Println(v)
}
3.1 给数据设置有效时间

说明:通过golang对redis *** 作,给 key-val设置有效时间

// 给name数据设置有效时间为10s
_, err = conn.Do("expire", "name", 10)
4. *** 作List

说明: 通过golang对redis *** 作List数据类型

_, err := conn.Do("lpush", "heroList", "no1:悟空", 30, "no2:八戒", 33)
r, err := redis.String(conn.Do("rpop", "heroList"))
5. Redis 链接池

说明:通过Golang对Redis *** 作,还可以通过Redis链接池,步骤:

1)事先初始化一定数量的链接,放入到链接池

2)当Go需要 *** 作Redis时,直接从Redis链接池取出链接即可

3)这样 可以节省临时获取Redis链接的时间,从而提高效率

4)示意图:

5 ) 链接池使用案例:

package main
import (
	"fmt"
	"github.com/garyburd/redigo/redis"
)
// 定义一个全局的pool
var pool *redis.Pool

//当线程启动时,就初始化链接池
func init() {
	pool = &redis.Pool {
		MaxIdle : 8, // 最大空闲连接数
		MaxActive : 0, // 表示和数据库的最大链接数,0 表示没有限制
		IdleTimeout : 100, // 最大空闲时间
		Dial : func()(redis.Conn, error) {
			// 初始化链接的代码,链接哪个ip的redis
			return redis.Dial("tcp", "localhost:6379")
		},
	}
} 

func main() {
	// 先从pool取出一个链接
	conn := pool.Get()
	defer conn.Close()

	_, err := conn.Do("Set", "name", "汤姆")
	if err != nil {
		fmt.Println("conn.Do err = ", err)
		return
	}

	// 取出
	r, err := redis.String(conn.Do("Get", "name"))
	if err != nil {
		fmt.Println("conn.Do err = ", err)
		return 
	}

	fmt.Println("r  = ", r)

	// 如果我们要从pool取出链接,一定保证链接池没有关闭
	// pool.Close()
	conn2 := pool.Get()  // 取第二个链接

	_, err = conn2.Do("Set","name2", "汤姆2")
	if err != nil {
		fmt.Println("conn.Do err = ", err)
		return
	}

	// 取出
	r2, err := redis.String(conn2.Do("Get", "name2"))
	if err != nil {
		fmt.Println("conn.Do err = ", err)
		return
	}

	fmt.Println("r = ", r2)
	// fmt.Println("conn2 = ", conn2)
}

注意:redis.Poll 结构介绍:

// github.com/garyburd/redigo/redis/pool.go
type Pool struct {

    // Dial()方法返回一个连接,从在需要创建连接到的时候调用
    Dial func() (Conn, error)

    // TestOnBorrow()方法是一个可选项,该方法用来诊断一个连接的健康状态
    TestOnBorrow func(c Conn, t time.Time) error

    // 最大空闲连接数
    MaxIdle int

    // 一个pool所能分配的最大的连接数目
    // 当设置成0的时候,该pool连接数没有限制
    MaxActive int

    // 空闲连接超时时间,超过超时时间的空闲连接会被关闭。
    // 如果设置成0,空闲连接将不会被关闭
    // 应该设置一个比redis服务端超时时间更短的时间
    IdleTimeout time.Duration

    // 如果Wait被设置成true,则Get()方法将会阻塞
    Wait bool

    // mu protects fields defined below.
    mu     sync.Mutex
    cond   *sync.Cond
    closed bool
    active int

    // 空闲连接队列
    idle list.List
}

主要参数:

MaxIdle

表示连接池空闲连接列表的长度限制空闲列表是一个栈式的结构,先进后出

MaxActive

表示连接池中最大连接数限制主要考虑到服务端支持的连接数上限,以及应用之间”瓜分”连接数

IdleTimeout

空闲连接的超时设置,一旦超时,将会从空闲列表中摘除该超时时间时间应该小于服务端的连接超时设置

区分两种使用场景:

高频调用的场景,需要尽量压榨redis的性能:

调高MaxIdle的大小,该数目小于maxActive,由于作为一个缓冲区一样的存在,扩大缓冲区自然没有问题调高MaxActive,考虑到服务端的支持上限,尽量调高IdleTimeout由于是高频使用场景,设置短一点也无所谓,需要注意的一点是MaxIdle设置的长了,队列中的过期连接可能会增多,这个时候IdleTimeout也要相应变化

低频调用的场景,调用量远未达到redis的负载,稳定性为重:

MaxIdle可以设置的小一些IdleTimeout相应地设置小一些
时间时间应该小于服务端的连接超时设置

区分两种使用场景:

高频调用的场景,需要尽量压榨redis的性能:

调高MaxIdle的大小,该数目小于maxActive,由于作为一个缓冲区一样的存在,扩大缓冲区自然没有问题调高MaxActive,考虑到服务端的支持上限,尽量调高IdleTimeout由于是高频使用场景,设置短一点也无所谓,需要注意的一点是MaxIdle设置的长了,队列中的过期连接可能会增多,这个时候IdleTimeout也要相应变化

低频调用的场景,调用量远未达到redis的负载,稳定性为重:

MaxIdle可以设置的小一些IdleTimeout相应地设置小一些MaxActive随意,够用就好,容易检测到异常

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/994347.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存