【Go】用 Go 访问 Redis
用 Go 訪問 Redis
Redis 官方并沒有提供 Redis 訪問包,官網列出來了很多 Go 語言的客戶端包,它們都能實現對 Redis 的訪問和操作,本文以其中較為人性化的 Redigo 來講解。
1. Redis 連接
獲取項目包:
$ go get github.com/gomodule/redigo接下來調用 redis.Dial() 連接 Redis 服務器:
package mainimport ("fmt""github.com/gomodule/redigo/redis" )func main() {c, err := redis.Dial("tcp", "localhost:6379")if err != nil {fmt.Println("conn redis failed, err:", err)return}defer c.Close() }2. Redis 設置和獲取字符串
最常用的是 Do() 方法,他可以支持 Redis 的 Set、Get、MSet、MGet、HSet、HGet 等常用命令:
_, err = c.Do("Set", "username", "jim") if err != nil {fmt.Println(err)return }在 Redigo 客戶端包中,通過調用 redis.String() 函數來獲取字符串:
res, err := redis.String(c.Do("Get", "username")) if err != nil {fmt.Println(err)return } fmt.Println(res)3. Redis 批量設置
可以用 Do() 批量設置字符串:
_, err = c.Do("MSet", "username", "james", "phone", "18888888888") if err != nil {fmt.Println("MSet error: ", err)return }4. Redis hash 操作
_, err = c.Do("HSet", "names", "jim", "barry") if err != nil {fmt.Println("hset error: ", 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 設置過期時間
_, err = c.Do("expire", "names", 5) if err != nil {fmt.Println("expire error: ", err)return }6. 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("llen error: ", err)return } fmt.Println(res4)7. 實現 Redis 連接池功能
為什么使用連接池? Redis也是一種數據庫,它基于 C/S 模式,因此如果需要使用,則必須先建立連接。C/S 模式就是一種遠程通信的交互模式,因此 Redis服務器可以單獨作為一個數據庫服務器獨立存在。
假設Reds服務器與客戶端分處異地,雖然基于內存的 Redis數據庫有著超高的性能,但是底層的網絡通信卻占用了一次數據請求的大量時間。因為,每次數據交互都需要先建立連接。假設一 次數據交互總共用時 30ms,超高性能的 Redis 數據庫處理數據所花的時間可能不到 1ms,也就是 說前期的連接占用了 29ms。
連接池則可以實現在客戶端建立多個與服務器的連接并且不釋放當需要使用連接時,通過一定的算法獲取已經建立的連接,使用完后則還給連接池,這就免去了連接服務器所占用的時間。
Redigo 客戶端包中通過 Pool 對象來建立連接池,其使用方法如下:
使用 Pool 結構體初始化一個連接池:
pool = &redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (redis.Conn, error) {return redis.Dial("tcp", "localhost:6379")},}調用 Do() 方法來設置和獲取字符串
完整代碼如下:
package mainimport ("fmt""github.com/gomodule/redigo/redis" )var pool *redis.Poolfunc init() {pool = &redis.Pool{MaxIdle: 16,MaxActive: 1024,IdleTimeout: 300,Dial: func() (redis.Conn, error) {return redis.Dial("tcp", "localhost:6379")},} }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) }8. Redis 實現管道操作
請求/響應服務可以實現持續處理新請求。客戶端可以發送多個命令到服務器端而無須等待響應,最后再一次性讀取多個響應。
Send()、 Flush()、 Receive()方法支持管道化操作。Send()方法用于向連接的輸出緩沖中寫入 命令。 Flush()方法用于將連接的輸出緩沖清空并寫入服務器端。 Recevie()方法用于按照 FIFO 順序依次讀取服務器端的響應。示例代碼如下:
package mainimport ("fmt""github.com/gomodule/redigo/redis" )func main() {c, err := redis.Dial("tcp", "localhost:6379")if err != nil {fmt.Println("conn redis failed, err:", 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) }結果輸出:
v:OK,err:<nil> v:OK,err:<nil>9. Redis 的并發
在日常開發中,有時會遇到這樣的場景:多個人時對同一個數據進行修改,導致并發問題發 生。使用 Redis來解決這個問題是很好的選擇。
Redis 管道使得客戶端能夠用“無等待響應”的方式,來連續發送多條命令請求至 Redis 服務器端,然后服務器端按照請求順序返回相應的結果。
Redis管道( Pipelining)的操作可以理解為并發操作,并通過 Send、 Flush、 Receivel 這3個方法實現客戶端可以用Send(方法一次性向服務器發送一個或多個命令。命令發送完畢后, 用 Flush() 方法將緩沖區的命令一次性發送到服務器端,客戶端再用 Receive() 方法依次按照先進先出的順序讀取所有命令的結果。 Redis并發的示例如下
package mainimport ("fmt""github.com/gomodule/redigo/redis" )func main() {conn, err := redis.Dial("tcp", "localhost:6379")if err != nil {fmt.Println("connect redis error :", err)return}defer conn.Close()conn.Send("HSET", "students", "name", "jim", "age", "19")conn.Send("HSET", "students", "score", "100")conn.Send("HGET", "students", "age")conn.Flush()res1, err := conn.Receive()fmt.Printf("Receive res1:%v \n", res1)res2, err := conn.Receive()fmt.Printf("Receive res2:%v\n", res2)res3, err := conn.Receive()fmt.Printf("Receive res3:%s\n", res3) }輸出結果:
Receive res1:<nil> Receive res2:1 Receive res3:%!s(<nil>)10. Redis 的事務
MULTI、EXEC、 DISCARD 和 WATCH 方法是構成 Redis 事務的基礎。使用 Go 語言對 Redis 進行事務操作的本質也是使用這些命令。
- MULTI:開啟事務;
- EXEC:執行事務;
- DISCARD:取消事務;
- WATCH:監視事務中的鍵變化,一旦有改變則取消事務
示例代碼:
package mainimport ("fmt""github.com/gomodule/redigo/redis" )func main() {conn, err := redis.Dial("tcp", "localhost:6379")if err != nil {fmt.Println("connect redis error :", err)return}defer conn.Close()conn.Send("MULTI")conn.Send("INCR", "foo")conn.Send("INCR", "bar")r, err := conn.Do("EXEC")fmt.Println(r) }總結
以上是生活随笔為你收集整理的【Go】用 Go 访问 Redis的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序登录注册流程(获取手机号)
- 下一篇: WikiTaxi_Importer_1.