Go劍復國-30天導入Golang Day23 Golang 如何使用 redis
今天要進入到,web屆,講到快取一定會提到的 redis 。 redis 真的是一種通用武器,不管你後端用什麼語言,還真沒看過沒人不會用 redis ,那當然我們就要介紹一下 redis 的基礎使用。
gomodule/redigo
這個套件,是我從寫 go 以來,只要是用碰到 redis 的相關應用,我一定會使用的第三方套件,它的主要維護者 Gary Burd,也是我前幾天介紹的 gorilla/mux的 gorilla 團隊另一個套件 gorilla/websocket 主要貢獻者,這個套件後面章節會介紹,我們接下來介紹他的基礎使用方式。
建構 connection pool
func main() {
pool := &redis.Pool{
// 連線的 callback 定義
Dial: func() (redis.Conn, error) {
//建構一條連線
c, err := redis.Dial("tcp", server)
if err != nil {
return nil, err
}
//在這邊可以做連線池初始化 選擇 redis db的動作
if _, err := c.Do("SELECT", db); err != nil {
c.Close()
return nil, err
}
return c, nil
},
//定期對 redis server 做 ping/pong 測試
TestOnBorrow: func(c redis.Conn, t time.Time) error {
if time.Since(t) < time.Minute {
return nil
}
_, err := c.Do("PING")
return err
},
}
}
使用連線
func main() {
pool := &redis.Pool{
// 連線的 callback 定義
Dial: func() (redis.Conn, error) {
//建構一條連線
c, err := redis.Dial("tcp", server)
if err != nil {
return nil, err
}
//在這邊可以做連線池初始化 選擇 redis db的動作
if _, err := c.Do("SELECT", db); err != nil {
c.Close()
return nil, err
}
return c, nil
},
//定期對 redis server 做 ping/pong 測試
TestOnBorrow: func(c redis.Conn, t time.Time) error {
if time.Since(t) < time.Minute {
return nil
}
_, err := c.Do("PING")
return err
},
}
//這邊要非常注意,redis用完連線,請一定要做close的動作,否則有機會造成 memory leak
// close完的連線,會回到 connection pool
conn := pool.Get()
defer conn.Close()
var value1 int
var value2 string
//這是package 提供的 helper
reply, err := redis.Values(conn.Do("MGET", "key1", "key2"))
if err != nil {
// handle error
}
//這是package提供的helper 幫助可以scan 相關數值
if _, err := redis.Scan(reply, &value1, &value2); err != nil {
// handle error
}
}
上面範例只有一個重點,請大家多多使用 redigo 提供的 connection pool,可以幫助你控管連線,而且也要記得每次使用完 conn ,也都要記得做 close,釋放連線。
pub/sub
在 redis 裡面,如果善用這個功能,就可以做到 event trigger 這個模式,而不是透過傳統輪詢的方式,來關注你的服務狀態是否已經改變。後面章節,會有一篇分享,我運用 redis 在架構面的設計。
func main() {
pool := &redis.Pool{
// 連線的 callback 定義
Dial: func() (redis.Conn, error) {
//建構一條連線
c, err := redis.Dial("tcp", server)
if err != nil {
return nil, err
}
//在這邊可以做連線池初始化 選擇 redis db的動作
if _, err := c.Do("SELECT", db); err != nil {
c.Close()
return nil, err
}
return c, nil
},
//定期對 redis server 做 ping/pong 測試
TestOnBorrow: func(c redis.Conn, t time.Time) error {
if time.Since(t) < time.Minute {
return nil
}
_, err := c.Do("PING")
return err
},
}
//這邊要非常注意,redis用完連線,請一定要做close的動作,否則有機會造成 memory leak
// close完的連線,會回到 connection pool
conn := pool.Get()
defer conn.Close()
//這邊運用 pub/sub helper
psc := redis.PubSubConn{Conn: conn}
psc.Subscribe("example")
for {
switch v := psc.Receive().(type) {
case redis.Message:
fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
case redis.Subscription:
fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
case error:
return v
}
}
}
這邊只是做基礎的 redis 應用介紹,需要更多說明,請到官方文件