Skip to content

Redis

Redis 是一個開源的使用 ANSI C 語言編寫、遵守 BSD 協議、支持網絡、可基於內存、分布式、可選持久性的鍵值對(Key-Value)存儲數據庫,並提供多種語言的 API,Redis 即可以當作一個 NoSQL 數據庫,又可以是當作高速緩存存儲,還支持簡單的消息隊列。

本文僅僅講解如何使用 Go 語言驅動來操作 Redis 數據庫,不會對 Redis 本身做任何講解。

官方文檔:Golang Redis client (uptrace.dev)

官方倉庫:go-redis/redis: Type-safe Redis client for Golang (github.com)

安裝

關於 Redis 的驅動有很多,本文使用的是github.com/go-redis/redis

如果你使用的 Redis 版本號為 6

go get github.com/go-redis/redis/v8

如果你使用的 Redis 版本號為 7

go get github.com/go-redis/redis/v9

快速開始

go
import (
   "fmt"
   "log"
   "testing"

   "github.com/go-redis/redis"
)

func TestQuickStart(t *testing.T) {
   // 創建Redis連接客戶端
   redisClient := redis.NewClient(&redis.Options{
      Addr:     "192.168.48.134:6379",
      Password: "123456",
      DB:       0, // 使用默認DB
   })

   // 設置鍵值對,0就是永不過期
   redisClient.Set("hello", "world", 0)

   // 讀取值
   result, err := redisClient.Get("hello").Result()
   if err == redis.Nil {
      fmt.Println("ket not exist")
   } else if err != nil {
      log.Panic(err)
   }
   fmt.Println(result)
}

連接配置

go
type Options struct {
  // 網絡類型 tcp 或者 unix.
  // 默認是 tcp.
  Network string
  // redis地址,格式 host:port
  Addr string

    // Dialer 創建一個新的網絡連接且比Network和Addr有著更高的優先級
  // Network and Addr options.
  Dialer func() (net.Conn, error)

  // 新建一個redis連接的時候,會回調這個函數
  OnConnect func(*Conn) error

  // redis密碼,redis server沒有設置可以為空。
  Password string

  // redis數據庫,序號從0開始,默認是0,可以不用設置
  DB int

  // redis操作失敗最大重試次數,默認0。
  MaxRetries int

  // 最小重試時間間隔.
  // 默認是 8ms ; -1 表示關閉.
  MinRetryBackoff time.Duration

  // 最大重試時間間隔
  // 默認是 512ms; -1 表示關閉.
  MaxRetryBackoff time.Duration

  // redis新連接超時時間.
  // 默認是 5 秒.
  DialTimeout time.Duration

  // socket讀取超時時間
  // 默認 3 秒.
  ReadTimeout time.Duration

  // socket寫超時時間
  WriteTimeout time.Duration

  // redis連接池的最大連接數.
  // 默認連接池大小等於 cpu個數 * 10
  PoolSize int

  // redis連接池最小空閒連接數.
  MinIdleConns int

  // redis連接最大的存活時間,默認不會關閉過時的連接.
  MaxConnAge time.Duration

  // 當你從redis連接池獲取一個連接之後,連接池最多等待這個拿出去的連接多長時間。
  // 默認是等待 ReadTimeout + 1 秒.
  PoolTimeout time.Duration

  // redis連接池多久會關閉一個空閒連接.
  // 默認是 5 分鐘. -1 則表示關閉這個配置項
  IdleTimeout time.Duration

  // 多長時間檢測一下,空閒連接
  // 默認是 1 分鐘. -1 表示關閉空閒連接檢測
  IdleCheckFrequency time.Duration

  // 只讀設置,如果設置為true, 在當前節點實例上,redis只能查詢緩存不能更新。
  readOnly bool

    // TLS配置
  TLSConfig *tls.Config
}

建立連接

go
// 創建Redis連接客戶端
redisClient := redis.NewClient(&redis.Options{
    Addr:     "192.168.48.134:6379",
    Password: "123456",
    DB:       0, // 使用默認DB
})

關閉連接

驅動內部維護著一個連接池,不需要操作一次就關閉一次連接。

go
defer redisClient.Close()

這個 Redis 驅動幾乎將所有的操作封裝好了,Redis 命令和方法名一一對應,基本上只要知道 Redis 命令怎麼用,驅動對應的方法都也差不多會了。

Redis 命令:redis 命令手冊

基本操作

刪除鍵

go
redisClient.Set("name", "jack", 0)
fmt.Println(redisClient.Del("name").Result())

過期時間

go
redisClient.Set("name", "jack", 0)
// 設置過期時間
redisClient.Expire("name", time.Second*2)
fmt.Println(redisClient.Get("name").Val())
time.Sleep(time.Second * 3)
fmt.Println(redisClient.Get("name").Val())

取消過期時間

go
redisClient.Set("name", "jack", 2)
// 取消過期時間
redisClient.Persist("name")
time.Sleep(time.Second * 2)
fmt.Println(redisClient.Get("name"))

查詢過期時間

go
fmt.Println(redisClient.TTL("name"))
fmt.Println(redisClient.PTTL("name"))

重命名

go
redisClient.Rename("name", "newName")

查詢類型

go
redisClient.Type("name")

掃描

go
fmt.Println(redisClient.Scan(0, "", 4))

字符串

簡單存取

go
redisClient.Set("token", "abcefghijklmn", 0)
fmt.Println(redisClient.Get("token").Val())

批量存取

go
redisClient.MSet("cookie", "12345", "token", "abcefg")
fmt.Println(redisClient.MGet("cookie", "token").Val())

數字增減

go
redisClient.Set("age", "1", 0)
// 自增
redisClient.Incr("age")
fmt.Println(redisClient.Get("age").Val())
// 自減
redisClient.Decr("age")
fmt.Println(redisClient.Get("age").Val())

哈希表

讀寫操作

go
// 單個設置
redisClient.HSet("map", "name", "jack")
// 批量設置
redisClient.HMSet("map", map[string]interface{}{"a": "b", "c": "d", "e": "f"})
// 單個訪問
fmt.Println(redisClient.HGet("map", "a").Val())
// 批量訪問
fmt.Println(redisClient.HMGet("map", "a", "b").Val())
// 獲取整個map
fmt.Println(redisClient.HGetAll("map").Val())

輸出

b
[b <nil>]
map[a:b c:d e:f name:jack]

刪除鍵

go
// 刪除map的一個字段
redisClient.HDel("map", "a")

判斷鍵是否存在

go
// 判斷字段是否存在
redisClient.HExists("map", "a")

獲取所有的鍵

go
// 獲取所有的map的鍵
redisClient.HKeys("map")

獲取哈希表鍵長度

go
// 獲取map長度
redisClient.HLen("map")

遍歷哈希表的鍵值對

go
// 遍歷map中的鍵值對
redisClient.HScan("map", 0, "", 1)

列表

修改元素

go
// 左邊添加
redisClient.LPush("list", "a", "b", "c", "d", "e")
// 右邊添加
redisClient.RPush("list", "g", "i", "a")
// 在參考值前面插入值
redisClient.LInsertBefore("list", "a", "aa")
// 在參考值後面插入值
redisClient.LInsertAfter("list", "a", "gg")
// 設置指定下標的元素的值
redisClient.LSet("list", 0, "head")

訪問長度

go
// 訪問列表長度
redisClient.LLen("list")

訪問元素

go
// 左邊彈出元素
redisClient.LPop("list")
// 右邊彈出元素
redisClient.RPop("list")
// 訪問指定下標的元素
redisClient.LIndex("list", 1)
// 訪問指定范圍內的元素
redisClient.LRange("list", 0, 1)

刪除元素

go
// 刪除指定元素
redisClient.LRem("list", 0, "a")
// 刪除指定范圍的元素
redisClient.LTrim("list", 0, 1)
// 保留指定范圍的元素
redisClient.LTrim("list", 0, 1)

集合

新增元素

go
// 往一個集合裡面添加元素
redisClient.SAdd("set", "a", "b", "c")
redisClient.SAdd("set2", "c", "d", "e")

訪問集合元素

go
// 獲取集合中的所有成員
redisClient.SMembers("set")
// 判斷一個元素是否屬於這個集合
redisClient.SIsMember("set", "a")
// 隨機返回count個元素
redisClient.SRandMemberN("set", 1)
// 獲取一個集合的元素個數
redisClient.SCard("set")

集合操作

go
// 返回給定集合的差集
redisClient.SDiff("set", "set2")
// 將給定集合的差集保存在結果集裡,返回結果集的長度
redisClient.SDiffStore("store", "set", "se2")
// 返回給定集合的交集
redisClient.SInter("set", "set2")
// 將給定集合的交集保存在結果集裡,返回結果集的長度
redisClient.SInterStore("store", "set", "set2")
// 返回給定集合的並集
redisClient.SUnion("set", "set2")
// 將給定集合的並集保存在結果集裡,返回結果集的長度
redisClient.SUnionStore("store", "set", "store")

刪除元素

go
// 彈出並刪除該元素
redisClient.SPop("set")
// 彈出並刪除N給元素
redisClient.SPopN("set", 2)

移動元素

go
// 從源集合移動指定元素刀目標集合
redisClient.SMove("set", "set2", "a")

刪除元素

go
// 刪除指定元素
redisClient.SRem("set", "a", "b")

遍歷

go
// 遍歷集合
redisClient.SScan("set", 0, "", 2)

有序集合

加入元素

go
// 往有序集合中加入元素
redisClient.ZAdd("ss", redis.Z{
   Score:  1,
   Member: "a",
}, redis.Z{
   Score:  2,
   Member: "b",
})

元素排名

go
// 返回有序集合中該元素的排名,從低到高排列
redisClient.ZRank("ss", "1")
// 返回有序集合中該元素的排名,從高到低排列
redisClient.ZRevRank("ss", "1")

訪問元素

go
// 返回介於min和max之間的成員數量
redisClient.ZCount("ss", "1", "2")

// 返回對元素的權值
redisClient.ZScore("ss", "a")

// 返回指定區間的元素
redisClient.ZRange("ss", 1, 2)
// 返回介於min和max之間的所有成員列表
redisClient.ZRangeByScore("ss", redis.ZRangeBy{
   Min:    "1",
   Max:    "2",
   Offset: 0,
   Count:  1,
})

修改權值

go
// 給一個對應的元素增加相應的權值
redisClient.ZIncr("ss", redis.Z{
   Score:  2,
   Member: "b",
})

刪除元素

go
// 刪除指定元素
redisClient.ZRem("ss", "a")
// 刪除指定排名區間的元素
redisClient.ZRemRangeByRank("ss", 1, 2)
// 刪除權值在min和max區間的元素
redisClient.ZRemRangeByScore("ss", "1", "2")

腳本

go
// 加載腳本,返回sha值
redisClient.ScriptLoad("return 0")
// 根據sha值執行腳本
redisClient.EvalSha("sha", []string{}, "")
// 直接執行腳本
redisClient.Eval("return 0", []string{}, "")
// 清除腳本緩存
redisClient.ScriptFlush()
// 殺死當前正在運行的腳本
redisClient.ScriptKill()
// 驗證對應哈希值的腳本是否存在
redisClient.ScriptExists("")

發布訂閱

go
// 發送消息到指定頻道
redisClient.Publish("channel", "message")
// 訂閱指定頻道
redisClient.Subscribe("channel")
// 查看訂閱狀態
redisClient.PubSubNumSub("channel")

Golang學習網由www.golangdev.cn整理維護