因为之前做的一个小网盘想实现一个分片上传,就尝试用了redis,对redis有了一些了解,具体可见:
Redis基础知识:https://blog.csdn.net/Lazyboy_/article/details/88819755
Redis基本操作:https://blog.csdn.net/Lazyboy_/article/details/88821948
现在要使用go语言对redis进行操作就要使用go的一些方法来实现了。
在golang中使用redis还是要站在前辈的肩膀上,用人家的库来实现操作。
import "github.com/garyburd/redigo/redis"
连接
conn接口是使用redis的主要接口。应用程序通过调用dial、dialwithTimeout或newconn函数来创建连接。将来,将添加用于创建分片连接和其他类型连接的功能。
当应用程序完成连接时,应用程序必须调用连接关闭方法。
type Conn interface { // Close closes the connection. Close() error // Err returns a non-nil value when the connection is not usable. Err() error // Do sends a command to the server and returns the received reply. Do(commandName string, args ...interface{}) (reply interface{}, err error) // Send writes the command to the client's output buffer. Send(commandName string, args ...interface{}) error // Flush flushes the output buffer to the Redis server. Flush() error // Receive receives a single reply from the Redis server Receive() (reply interface{}, err error) } // 使用指定的选项连接到给定网络和地址的Redis服务器。 func Dial(network, address string, options ...DialOption) (Conn, error)
var ( redisHost = "127.0.0.1:6379" redisPass = "1234" ) func main() { c,err := redis.Dial("tcp", redisHost) if err != nil { fmt.Println(err.Error()) return } defer c.Close() // 这里因为我设置了密码,所以要连接必须得使用Do方法输入密码 if _,err := c.Do("AUTH", redisPass); err != nil { fmt.Println(err.Error()) return } }
执行命令
conn接口具有执行redis命令的通用方法:
Do(commandName string, args ...interface{}) (reply interface{}, err error)
http://redis.io/commands 列出了可用的命令
do方法将命令参数转换为大容量字符串,以便传输到服务器,如上图中传递密码的Do方法。
redis的所有命令操作都可以通过Do方法来实现,只是args的数量问题。
我们通过连接redis执行对string的set和get操作,并设置超时时间。
package main import ( "fmt" "time" "github.com/garyburd/redigo/redis" ) var ( redisHost = "127.0.0.1:6379" redisPass = "1234" ) func main() { c,err := redis.Dial("tcp", redisHost) if err != nil { fmt.Println(err.Error()) return } defer c.Close() if _,err := c.Do("AUTH", redisPass); err != nil { fmt.Println(err.Error()) return } _, err = c.Do("SET", "name", "lazyboy", "EX", "5") if err != nil { fmt.Println("redis set failed:", err) } /* 也可以通过下面这段函数为key设置超时时间 _, err = c.Do("expire", "name", 10) //10秒过期 if err != nil { fmt.Println("set expire error: ", err) return }*/ username, err := redis.String(c.Do("GET", "name")) if err != nil { fmt.Println("redis get failed:", err) } else { fmt.Printf("Get name: %v \n", username) } time.Sleep(8 * time.Second) username, err = redis.String(c.Do("GET", "name")) if err != nil { fmt.Println("redis get failed:", err) } else { fmt.Printf("Get name: %v \n", username) } }
这里可能返回多个值或不能直接使用的值,但是都是存在一个变量中,需要通过一些类型转换、反射等操作得到需要的正确类型值。
Pool连接池
type Pool struct { // Dial is an application supplied function for creating and configuring a // connection. // // The connection returned from Dial must not be in a special state // (subscribed to pubsub channel, transaction started, ...). Dial func() (Conn, error) //连接 {} // TestOnBorrow is an optional application supplied function for checking // the health of an idle connection before the connection is used again by // the application. Argument t is the time that the connection was returned // to the pool. If the function returns an error, then the connection is // closed. TestOnBorrow func(c Conn, t time.Time) error {} // Maximum number of idle connections in the pool. MaxIdle int // 最大空闲连接数 // Maximum number of connections allocated by the pool at a given time. // When zero, there is no limit on the number of connections in the pool. MaxActive int // 最大激活连接数 // Close connections after remaining idle for this duration. If the value // is zero, then idle connections are not closed. Applications should set // the timeout to a value less than the server's timeout. IdleTimeout time.Duration // 空闲连接等待超时时间 // If Wait is true and the pool is at the MaxActive limit, then Get() waits // for a connection to be returned to the pool before returning. Wait bool // 当配置项为true并且MaxActive参数有限制时候,使用Get方法等待一个连接返回给连接池 // Close connections older than this duration. If the value is zero, then // the pool does not close connections based on age. MaxConnLifetime time.Duration // contains filtered or unexported fields }
Pool维护了一个连接池, 应用程序调用Get()方法从池中获取连接,并调用连接的close方法将连接的资源返回池。
func NewPool(newFn func() (Conn, error), maxIdle int) *Pool // 返回一个连接池 {} func (p *Pool) ActiveCount() int // 返回池中链接的个数 {} func (p *Pool) Close() error // 关闭连接池释放资源 {} func (p *Pool) Get() Conn // 获取连接conn {} func (p *Pool) GetContext(ctx context.Context) (Conn, error)// 根据context获取连接 {} func (p *Pool) IdleCount() int // 返回空闲连接数 {} func (p *Pool) Stats() PoolStats // 返回pool的统计信息 {}
举个栗子:
redis.Pool{ MaxIdle : 50, MaxActive : 30, IdleTimeout : 300*time.Second, Dial: func() (redis.Conn, error) { //1. 打开连接 c,err := redis.Dial("tcp", redisHost) if err != nil { fmt.Println(err) return nil, err } //2. 访问认证 if _,err := c.Do("AUTH",redisPass); err != nil { c.Close() return nil, err } return c, nil }, TestOnBorrow: func(conn redis.Conn, t time.Time) error { if time.Since(t) < time.Minute { return nil } _,err := conn.Do("PING") return err }, } rConn := redis.Pool.Get() defer rConn.Close()
这个是从我的程序中截的一节,上边的初始化是放在一个函数中的,为了方便阅读直接拿出来,下面两行是连接池的连接Get()方法,和释放连接Close()。
Redigo还有更多关于Redis的操作,暂时没有操作经验,先留着以后填坑。
参考资料:
1. https://godoc.org/github.com/garyburd/redigo/redis#Conn
2. https://blog.csdn.net/wangshubo1989/article/details/75050024
记录每天解决的小问题,积累起来去解决大问题。