GoWeb——访问Redis(Redigo)

Go访问Redis

Redis连接

Go语言官方并没有提供Redis访问包。在Redis官网上有很多Go语言的客户端包,它们都能实现对Redis的访问和操作。

相对来说Rdig()使用起来更人性化。重要的是,其源代码结构很清晰,而且其支持管道、发布和订阅、连接池等。所以选择Redigo作为示例讲解。

  1. Redis连接

获取项目包,命令行输入:

go get github.com/gomodule/redigo
import (
	"fmt"
	"github.com/gomodule/redigo/redis"
)

/*
用redis.Dial()函数连接Redis服务器
*/
func main() {
	c, err := redis.Dial("tcp", "localhost:6379",
		redis.DialPassword("123456"),
		redis.DialDatabase(1))
	if err != nil {
		fmt.Println("conn redis failed, err:", err)
		return
	}
	defer c.Close()
}
  1. Redis设置和获取字符串

Redigo客户端包中最常用的是Do()方法,它可以直接支持Redis的Set、Get、MSet、MGet、HSet、HGet等常用命令。下面示例代码是通过调用Do()方法来设置字符串:

//设置字符串
_, err = c.Do("Set", "username", "jack")
if err != nil {
	fmt.Println(err)
	return
}

通过redis.String()函数来获取字符串:

//获取字符串
res, err := redis.String(c.Do("get", "username"))
if err != nil {
	fmt.Println(err)
	return
}
fmt.Println(res)
  1. 批量设置

在Redigo客户端包中,可以用Do()方法来批量设置字符串;可以用redis.Strings()函数配合Do()方法来批量获取字符串:

//批量设置字符串
_, err = c.Do("MSet", "username", "james", "phone", "18812345678")
if err != nil {
	fmt.Println("MSet error:", err)
	return
}
//批量获取字符串
res2, err := redis.Strings(c.Do("MGet", "username", "phone"))
if err != nil {
	fmt.Println(err)
	return
}
fmt.Println(res2)
  1. Redis hash操作

在Redigo客户端包中,可以用Do()方法来设置和获取hash类型:

//hash操作
_, err = c.Do("HSet", "names", "jim", "barry")
if err != nil {
	fmt.Println(err)
	return
}
res3, err := redis.String(c.Do("HGet", "names", "jim"))
if err != nil {
	fmt.Println("hget error:", err)
	return
}
fmt.Println(res3)

5.Redis设置过期时间

在Redigo客户端包中,可以用Do()方法来设置过期时间:

//设置过期时间
_, err = c.Do("expire", "names", 10)
if err != nil {
	fmt.Println("expire error:", err)
	return
}
  1. Redis队列
//队列
_, err = c.Do("lpush", "Queue", "jim", "barry", 9)
if err != nil {
	fmt.Println("lpush error:", err)
	return
}
for {
	r, err := redis.String(c.Do("lpop", "Queue"))
	if err != nil {
		fmt.Println("lpop error:", err)
		break
	}
	fmt.Println(r)
}
res4, err := redis.Int(c.Do("llen", "Queue"))
if err != nil {
	fmt.Println(err)
	return
}
fmt.Println(res4)
  1. 实现Redis连接池功能

为什么使用连接池?Redis也是一种数据库,它基于C/S模式,因此如果需要使用,则必须先建立连接。C/S模式就是一种远程通信的交互模式,因此Redis服务器可以单独作为一个数据库服务器独立存在。

假设Redis服务器与客户端分处异地,虽然基于内存的Redis数据库有着超高的性能,但是底层的网络通信却占用了一次数据请求的大量时间。因为,每次数据交互都需要先建立连接。假设一次数据交互总共用时30ms,超高性能的Redis数据库处理数据所花的时间可能不到1ms,也就是说前期的连接占用了29ms。

连接池则可以实现在客户端建立多个与服务器的连接并且不释放。当需要使用连接时,通过一定的算法获取已经建立的连接,使用完后则还给连接池,这就免去了连接服务器所占用的时间。

Redigo客户端包中通过Pool对象来建立连接池,其使用方法如下。

1、使用Pool结构体初始化一个连接池
pool = &redis.Pool{
		MaxIdle: 16,
		MaxActive: 1024,
		IdleTimeout: 300,
		Dial: func() (redis.Conn, error) {
			return redis.Dial("tcp", "localhost:6379", redis.DialPassword("123456"))
		},
	}

该结构体各字段的解释如下:

  • Maxldle:最大的空闲连接数,表示即使在没有Redis连接时,依然可以保持n个空闲的连接,随时处于待命状态。
  • MaxActive:最大的激活连接数,表示同时最多有n个连接。
  • IdleTimeout:最大的空闲连接等待时间,超过此时间后空闲连接将被关闭。
2、调用Do()方法来设置和获取字符串
import (
	"fmt"
	"github.com/gomodule/redigo/redis"
)

/*
 使用连接池
*/
var pool *redis.Pool

func init() {
	pool = &redis.Pool{
		MaxIdle:     16,
		MaxActive:   1024,
		IdleTimeout: 300,
		Dial: func() (redis.Conn, error) {
			return redis.Dial("tcp", "localhost:6379", redis.DialPassword("123456"))
		},
	}
}

func main() {
	c := pool.Get()
	defer c.Close()

	_, err := c.Do("Set", "username", "jack")
	if err != nil {
		fmt.Println(err)
		return
	}
	r, err := redis.String(c.Do("Get", "username"))
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(r)
}
  1. Redis实现管道操作

请求/响应服务可以实现持续处理新请求。客户端可以发送多个命令到服务器端而无须等待响应,最后再一次性读取多个响应。

Send()、Flush()、Receive()方法支持管道化操作。Send()方法用于向连接的输出缓冲中写入命令。Flush()方法用于将连接的输出缓冲清空并写入服务器端。Recevie()方法用于按照FIFO顺序依次读取服务器端的响应。示例代码如下。

/*
管道操作
*/
func main() {
	c, err := redis.Dial("tcp", "localhost:6379",
		redis.DialPassword("123456"),
		redis.DialDatabase(0))
	if err != nil {
		fmt.Println(err)
		return
	}
	defer c.Close()

	c.Send("Set", "username1", "jim")
	c.Send("Set", "username2", "jack")
	c.Flush()

	v, err := c.Receive()
	fmt.Printf("v:%v, err:%v\n", v, err)
	v, err = c.Receive()
	fmt.Printf("v:%v, err:%v\n", v, err)
	v, err = c.Receive() //一直等待
	fmt.Printf("v:%v, err:%v\n", v, err)
}
  1. Redis的并发

在日常开发中,有时会遇到这样的场景:多个人同时对同一个数据进行修改,导致并发问题发生。使用Redis来解决这个问题是很好的选择。

Redis管道使得客户端能够用“无等待响应”的方式,来连续发送多条命令请求至Redis服务器端,然后服务器端按照请求顺序返回相应的结果。类似于如下形式:

client> set key1 value1;
client> set key2 value2;
client> set key3 value3;
server> ok
server> ok
server> ok

Redis管道(Pipelining)的操作可以理解为并发操作,并通过Send()、Flush()、Receive()这3个方法实现。客户端可以用Send()方法一次性向服务器发送一个或多个命令。命令发送完毕后,用Flush()方法将缓冲区的命令一次性发送到服务器端,客户端再用Receive()方法依次按照先进先
出的顺序读取所有命令的结果。Redis并发的示例如下。

import (
	"fmt"
	"github.com/gomodule/redigo/redis"
)

func main() {
	c, err := redis.Dial("tcp", "localhost:6379",
		redis.DialPassword("123456"),
		redis.DialDatabase(0))
	if err != nil {
		fmt.Println(err)
		return
	}
	defer c.Close()

	c.Send("HSet", "students", "name", "jim", "age", "19")
	c.Send("HSet", "students", "score", "100")
	c.Send("HGET", "students", "age")
	c.Flush()

	res1, err := c.Receive()
	fmt.Printf("Receive res1:%v\n", res1)
	res2, err := c.Receive()
	fmt.Printf("Receive res2:%v\n", res2)
	res3, err := c.Receive()
	fmt.Printf("Receive res3:%s\n", res3)
}
  1. Redis的事务

MULTI、EXEC、DISCARD和NATCH方法是构成Redis事务的基础。使用Go语言对Redis进行事务操作的本质也是使用这些命令。

  • MULTI:开启事务;
  • EXEC:执行事务;
  • DISCARD:取消事务;
  • WATCH:监视事务中的键变化,一旦有改变则取消事务;
/*
事务
*/
func main() {
	c, err := redis.Dial("tcp", "localhost:6379",
		redis.DialPassword("123456"),
		redis.DialDatabase(0))
	if err != nil {
		fmt.Println(err)
		return
	}
	defer c.Close()

	c.Send("MULTI")
	c.Send("WATCH", "foo")
	c.Send("INCR", "foo")
	c.Send("INCR", "bar")
	r, err := c.Do("EXEC")
	fmt.Println(r)
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值