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 コマンドとメソッド名が 1 対 1 に対応しています。基本的に 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 のフィールドを 1 つ削除
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整理维护