こんにちは。Tomoyuki(@tomoyuki65)です。
データベースには様々な種類がありますが、キャッシュによるパフォーマンス改善やセッション管理などの一時的なデータ保存、そしてリアルタイム性が求められる場面で利用されるデータストアとして、『Redis』があります。
ということでこの記事では、Go言語(Golang)でRedisの使い方についてまとめます。
Go言語(Golang)でRedisの使い方|Docker環境構築+サンプルAPI
Redisとは?
Redisは、メモリ(RAM)上でデータを管理するインメモリ型のデータストアで、非常に高速にデータを処理できるのが特徴です。
基本的にはキーと値の形式で保存しますが、リスト、セット、ハッシュ、ソート済みセットなどもサポートしています。
ただし、データの永続保存には向いていないため、メインのデータベースを補完する役割として使われることが一般的です。
Redisの主な用途
・キャッシュ
・WebページやAPIレスポンスの高速化
・セッション管理
・TTLで自動的に期限切れにできる
・リアルタイムランキング / スコア管理
・ソート付きセットを活用
・一時データ / TTL付きデータの保存
・ワンタイムトークン
・レート制限(アクセス制御)
・メッセージキュー / 非同期処理
・Pub/Subでチャットや通知機能
・リアルタイム分析 / データ集計
・アクセス数やイベントの集計
DockerでRedisのコンテナを立てる方法
ではDockerを使い、ローカル開発環境としてRedisのコンテナを立ててみます。
まずは以下のコマンドを実行し、ファイルを作成します。
$ mkdir go-redis && cd go-redis
$ touch compose.yml
次に作成したファイルを以下のように記述します。
・「compose.yml」
services:
redis:
image: redis:8.6.2
container_name: redis
command: redis-server
ports:
- "6379:6379"
volumes:
- redis-data:/data
volumes:
redis-data:
次に以下のコマンドを実行し、Dockerコンテナの起動を行います。
$ docker compose up -d
次に以下のコマンドを実行し、Dockerコンテナの起動を確認します。
$ docker compose ps
コマンド実行後、以下のようにredisコンテナが起動していればOKです。

Redisの使い方
Redisに接続する
Redisに接続して利用したい場合は、まずは以下のコマンドを実行してRedisコンテナへ入ります。
$ docker compose exec redis bash
次にRedisコンテナ内で以下のコマンドを実行し、Redisに接続します。
redis-cli --raw
※マルチバイト文字列の文字化けを防ぐため、オプション「–raw」付けています。
Redisに接続後、以下のように表示されればOKです。

以下を入力して実行し、レスポンスが返ってくるのを確認します。
PING
実行後、以下のようにPONが返ってこればOKです。

キーバリュー形式で文字列の値を登録
次に基本となるキーバリュー形式で文字列の値を登録する方法をご紹介します。
キーを「name」、値を「田中太郎」とし、以下のようにSETコマンドを実行します。
SET name 田中太郎
実行後、以下のようにOKが表示されれば成功です。

キーから登録済みの値を取得
次にキーを使って登録済みの値を取得するには、以下のようにGETコマンドを実行します。
GET name
実行後、以下のように値が取得できればOKです。

登録済みのキーバリューを削除
次に登録済みのキーバリューを削除したい場合は、以下のようにDELコマンドを実行します。
DEL name
実行後、以下のように1が返って来れば成功です。

※キーが存在しない場合は0が返ります。
再度GETコマンドを実行し、値が取得できなければOKです。

文字列の値を登録する際のオプション一覧
| オプション | 用途 | コマンド例 |
|---|---|---|
| EX seconds | 有効期限を秒単位で設定。指定秒後に自動削除される | SET mykey “Hello” EX 60 |
| PX milliseconds | 有効期限をミリ秒単位で設定 | SET mykey “Hello” PX 1500 |
| NX | キーが存在しない場合のみ設定(新規作成専用) | SET mykey “Hello” NX |
| XX | キーが存在する場合のみ設定(更新専用) | SET mykey “Hello” XX |
| KEEPTTL | 既存のTTL(有効期限)がある場合、それを保持して値を更新 | SET mykey “Hello” KEEPTTL |
| GET | 古い値を返す。設定前の値を取得可能(Redis 6.2以降) | SET mykey “Hello” GET |
※オプションを利用すれば有効期限の設定等が可能です。
その他のデータ型を操作するコマンド一覧
| データ型 | 主なコマンド | 主なパラメータ | 主なオプション | 用途 | コマンド例 |
|---|---|---|---|---|---|
| ハッシュ (Hash) | HSET, HGET, HGETALL, HDEL | フィールド名、値 | なし | オブジェクトの属性管理(例:ユーザー情報) | HSET user:1 name “Alice” HGET user:1 name HGETALL user:1 |
| リスト (List) | LPUSH, RPUSH, LPOP, RPOP, LRANGE | 追加する値、取得範囲(start stop) | LPUSHX / RPUSHX(既存キーのみ追加) | キューやスタック、順序付きコレクション | LPUSH tasks “task1” RPUSH tasks “task2” LRANGE tasks 0 -1 |
| セット (Set) | SADD, SREM, SMEMBERS, SISMEMBER, SINTER | セットに追加・削除・検索する要素(値) | なし | ユニーク要素の管理、集合演算 | SADD tags “redis” SREM tags “oldtag” SMEMBERS tags |
| ソート済みセット (Sorted Set / ZSet) | ZADD, ZREM, ZRANGE, ZRANGEBYSCORE | 追加する要素(値)とスコア、スコア範囲 | WITHSCORES(スコア表示) | ランキング、リーダーボード | ZADD leaderboard 100 “Alice” ZRANGE leaderboard 0 -1 WITHSCORES |
| ビットマップ | SETBIT, GETBIT, BITCOUNT | オフセット、値(0 or 1) | なし | フラグ管理、アクティブユーザー判定 | SETBIT login:2026-04-01 123 1 GETBIT login:2026-04-01 123 |
| HyperLogLog | PFADD, PFCOUNT, PFMERGE | 追加する要素(値) | なし | 大量データのユニーク数近似 | PFADD uv “user1” PFCOUNT uv |
| Geo(地理空間) | GEOADD, GEORADIUS, GEORADIUSBYMEMBER, GEODIST, GEOPOS | 経度・緯度・メンバー、中心座標・半径・単位(m/km/mi/ft) | なし | 位置情報管理、半径検索 | GEOADD cities 139.6917 35.6895 Tokyo GEORADIUS cities 139 35 50 km GEODIST cities Tokyo Osaka km |
※文字列以外にも色々対応してます。
Go言語(Golang)でRedisを操作するサンプルAPIを作って試す
Go言語(Golang)でサンプルAPIの準備
次にGoのサンプルAPIを準備します。まずは以下のコマンドを実行し、上記で起動中のDockerコンテナを止めます。
$ docker compose down
次に以下のコマンドを実行し、各種ファイルを作成します。
$ mkdir -p docker/local/go && touch docker/local/go/Dockerfile
$ mkdir src && touch src/main.go
$ touch .env
次に作成したファイルをそれぞれ以下のように記述します。
・「docker/local/go/Dockerfile」
FROM golang:1.26.1-alpine3.23
WORKDIR /go/src
COPY ./src .
# go.modがあれば依存関係をインストール
RUN if [ -f ./go.mod ]; then \
go install; \
fi
# 開発用のライブラリをインストール
RUN go install github.com/air-verse/air@v1.64.5
RUN go install honnef.co/go/tools/cmd/staticcheck@latest
EXPOSE 8080
・「src/main.go」
package main
import (
"log/slog"
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
// echoのルーター設定
e := echo.New()
e.GET("/", func(c echo.Context) error {
// レスポンス結果の設定
res := map[string]string{
"message": "Hello World !!",
}
return c.JSON(http.StatusOK, res)
})
// ログ出力
slog.Info("start go-redis")
// サーバー起動
e.Logger.Fatal(e.Start(":8080"))
}
・「.env」
ENV=local
REDIS_ADDR=redis:6379
REDIS_PASSWORD=
REDIS_DB=0
REDIS_DIAL_TIMEOUT=5
REDIS_READ_TIMEOUT=3
REDIS_WRITE_TIMEOUT=3
REDIS_TLS=false
REDIS_RETRY_COUNT=5
※環境変数「REDIS_PASSWORD」と「REDIS_TLS」は本番環境で利用する可能性があります。
次にファイル「compose.yml」を以下のように修正します。
services:
api:
container_name: go-redis-api
build:
context: .
dockerfile: ./docker/local/go/Dockerfile
command: air -c .air.toml
volumes:
- ./src:/go/src
ports:
- "8080:8080"
env_file:
- .env
tty: true
stdin_open: true
depends_on:
- redis
redis:
image: redis:8.6.2
container_name: redis
command: redis-server
ports:
- "6379:6379"
volumes:
- redis-data:/data
volumes:
redis-data:
次に以下のコマンドを実行し、Dockerコンテナをビルドします。
$ docker compose build --no-cache
次に以下のコマンドを実行し、Go言語の初期化処理を行います。
$ docker compose run --rm api go mod init go-redis
$ docker compose run --rm api go mod tidy
$ docker compose run --rm api air init
次に以下のコマンドを実行し、Dockerコンテナの再ビルドと起動を行います。
$ docker compose build --no-cache
$ docker compose up -d
次に以下のコマンドを実行し、Dockerコンテナの起動を確認します。
$ docker compose ps
コマンド実行後、以下のようにapiとredisのコンテナがそれぞれ起動していればOKです。

次にブラウザで「http://localhost:8080」を開き、JSON形式で想定通りのメッセージが出力されていればOKです。

Redisを操作するサンプルAPIを追加
次にGo言語(Golang)でRedisを操作するサンプルAPIを作って試します。
まずは以下のコマンドを実行し、各種ファイルを作成します。
$ mkdir -p src/internal/infrastructure/database && touch src/internal/infrastructure/database/redis.go
次に作成したファイルを以下のように記述します。
・「src/internal/infrastructure/database/redis.go」
package database
import (
"context"
"crypto/tls"
"fmt"
"os"
"strconv"
"time"
"github.com/redis/go-redis/v9"
)
func NewRedisClientWithRetry(ctx context.Context) (*redis.Client, error) {
// 環境変数から接続設定値を取得
addr := os.Getenv("REDIS_ADDR")
if addr == "" {
addr = "localhost:6379"
}
// パスワード設定(本番環境用)
password := os.Getenv("REDIS_PASSWORD")
// Redisの論理データベース番号 (0〜15のインデックス。デフォルトは0)
db := 0
if dbStr := os.Getenv("REDIS_DB"); dbStr != "" {
if parsedDB, err := strconv.Atoi(dbStr); err == nil {
db = parsedDB
}
}
// Redisとの接続確立までの制限時間の設定
dialTimeout := 5 * time.Second
if dt := os.Getenv("REDIS_DIAL_TIMEOUT"); dt != "" {
if sec, err := strconv.Atoi(dt); err == nil {
dialTimeout = time.Duration(sec) * time.Second
}
}
// Redisからのレスポンスを待つ制限時間の設定
readTimeout := 3 * time.Second
if rt := os.Getenv("REDIS_READ_TIMEOUT"); rt != "" {
if sec, err := strconv.Atoi(rt); err == nil {
readTimeout = time.Duration(sec) * time.Second
}
}
// Redisにリクエストを書き込む(送信する)処理の制限時間の設定
writeTimeout := 3 * time.Second
if wt := os.Getenv("REDIS_WRITE_TIMEOUT"); wt != "" {
if sec, err := strconv.Atoi(wt); err == nil {
writeTimeout = time.Duration(sec) * time.Second
}
}
// 通信の暗号化設定(本番環境用)
var tlsConfig *tls.Config
if os.Getenv("REDIS_TLS") == "true" {
tlsConfig = &tls.Config{
MinVersion: tls.VersionTLS12,
}
}
// Redisへの接続失敗時のリトライ回数
retryCount := 5
if rc := os.Getenv("REDIS_RETRY_COUNT"); rc != "" {
if parsedRC, err := strconv.Atoi(rc); err == nil {
retryCount = parsedRC
}
}
// Redisクライアントの設定
rdb := redis.NewClient(&redis.Options{
Addr: addr,
Password: password,
DB: db,
DialTimeout: dialTimeout,
ReadTimeout: readTimeout,
WriteTimeout: writeTimeout,
TLSConfig: tlsConfig,
})
// 接続確認(リトライ有り)
var err error
for i := 0; i < retryCount; i++ {
if err = rdb.Ping(ctx).Err(); err == nil {
return rdb, nil
}
fmt.Printf("redis ping failed, retrying... (%d/%d)\n", i+1, retryCount)
time.Sleep(1 * time.Second)
}
return nil, fmt.Errorf("failed to connect to Redis after %d retries: %w", retryCount, err)
}
※これはRedisへの接続用の設定ファイルです。
次にファイル「src/main.go」を以下のように修正します。
package main
import (
"fmt"
"log/slog"
"net/http"
"time"
"github.com/labstack/echo/v4"
"github.com/redis/go-redis/v9"
"go-redis/internal/infrastructure/database"
)
// Redisへのデータ登録用リクエストボディの構造体
type SetRedisRequestBody struct {
Key string `json:"key"`
Value string `json:"value"`
TTLSeconds int `json:"ttlSeconds"`
Mode string `json:"mode"`
KeepTTL bool `json:"keepTTL"`
}
func main() {
// echoのルーター設定
e := echo.New()
e.GET("/", func(c echo.Context) error {
// レスポンス結果の設定
res := map[string]string{
"message": "Hello World !!",
}
return c.JSON(http.StatusOK, res)
})
// サンプルAPIを追加
apiV1 := e.Group("/api/v1")
// Redisへのデータ登録
apiV1.POST("/redis/set", func(c echo.Context) error {
// リクエストボディの取得
var reqBody SetRedisRequestBody
if err := c.Bind(&reqBody); err != nil {
return err
}
// チェック処理(ライブラリは使わずKey、Value、Modeの必須チェック)
if reqBody.Key == "" {
return echo.NewHTTPError(http.StatusBadRequest, "key is required")
}
if reqBody.Value == "" {
return echo.NewHTTPError(http.StatusBadRequest, "value is required")
}
if reqBody.Mode == "" {
return echo.NewHTTPError(http.StatusBadRequest, "mode is required")
}
// TTL設定(デフォルト0)
var ttl time.Duration = 0
if reqBody.TTLSeconds > 0 {
ttl = time.Duration(reqBody.TTLSeconds) * time.Second
}
ctx := c.Request().Context()
// redisクライアントの取得
rdb, err := database.NewRedisClientWithRetry(ctx)
if err != nil {
errMsg := fmt.Sprintf("failed to get redis client: %v", err)
return echo.NewHTTPError(http.StatusInternalServerError, errMsg)
}
// データ登録処理
switch reqBody.Mode {
case "create": // オプション「NX」(キーが存在しない場合のみ登録)
if err := rdb.SetArgs(ctx, reqBody.Key, reqBody.Value, redis.SetArgs{
Mode: "NX",
TTL: ttl,
}).Err(); err != nil {
errMsg := fmt.Sprintf("failed to set redis: %v", err)
return echo.NewHTTPError(http.StatusInternalServerError, errMsg)
}
case "update": // オプション「XX」(キーが存在する場合のみ更新)
// KeepTTL対応
if reqBody.KeepTTL {
ttlVal, err := rdb.TTL(ctx, reqBody.Key).Result()
if err != nil {
errMsg := fmt.Sprintf("failed to set redis: %v", err)
return echo.NewHTTPError(http.StatusInternalServerError, errMsg)
}
if ttlVal > 0 {
ttl = ttlVal
}
}
if err := rdb.SetArgs(ctx, reqBody.Key, reqBody.Value, redis.SetArgs{
Mode: "XX",
TTL: ttl,
}).Err(); err != nil {
errMsg := fmt.Sprintf("failed to set redis: %v", err)
return echo.NewHTTPError(http.StatusInternalServerError, errMsg)
}
case "upsert": // 通常
// KeepTTL対応
if reqBody.KeepTTL {
ttlVal, err := rdb.TTL(ctx, reqBody.Key).Result()
if err != nil {
errMsg := fmt.Sprintf("failed to set redis: %v", err)
return echo.NewHTTPError(http.StatusInternalServerError, errMsg)
}
if ttlVal > 0 {
ttl = ttlVal
}
}
if err = rdb.Set(ctx, reqBody.Key, reqBody.Value, ttl).Err(); err != nil {
errMsg := fmt.Sprintf("failed to set redis: %v", err)
return echo.NewHTTPError(http.StatusInternalServerError, errMsg)
}
default:
return echo.NewHTTPError(http.StatusInternalServerError, "failed to set redis: invalid mode")
}
return c.JSON(http.StatusOK, map[string]string{
"message": "OK",
})
})
// Redisからデータ取得(文字列)
apiV1.GET("/redis/get/:key", func(c echo.Context) error {
// リクエストパラメータの取得
key := c.Param("key")
if key == "" {
return echo.NewHTTPError(http.StatusBadRequest, "key is required")
}
ctx := c.Request().Context()
// redisクライアントの取得
rdb, err := database.NewRedisClientWithRetry(ctx)
if err != nil {
errMsg := fmt.Sprintf("failed to get redis client: %v", err)
return echo.NewHTTPError(http.StatusInternalServerError, errMsg)
}
// データ取得処理
val, err := rdb.Get(ctx, key).Result()
if err != nil {
// キーが存在しない場合は空のオブジェクトを返す
if err == redis.Nil {
return c.JSON(http.StatusOK, map[string]interface{}{})
}
errMsg := fmt.Sprintf("failed to get redis: %v", err)
return echo.NewHTTPError(http.StatusInternalServerError, errMsg)
}
return c.JSON(http.StatusOK, map[string]string{
"value": val,
})
})
// Redisからデータ削除
apiV1.DELETE("/redis/del/:key", func(c echo.Context) error {
// リクエストパラメータの取得
key := c.Param("key")
if key == "" {
return echo.NewHTTPError(http.StatusBadRequest, "key is required")
}
ctx := c.Request().Context()
// redisクライアントの取得
rdb, err := database.NewRedisClientWithRetry(ctx)
if err != nil {
errMsg := fmt.Sprintf("failed to get redis client: %v", err)
return echo.NewHTTPError(http.StatusInternalServerError, errMsg)
}
// データ削除処理
res, err := rdb.Del(ctx, key).Result()
if err != nil {
errMsg := fmt.Sprintf("failed to delete redis: %v", err)
return echo.NewHTTPError(http.StatusInternalServerError, errMsg)
}
// キーが存在しない場合はエラー
if res == 0 {
return echo.NewHTTPError(http.StatusNotFound, "key not found")
}
return c.NoContent(http.StatusNoContent)
})
// ログ出力
slog.Info("start go-redis")
// サーバー起動
e.Logger.Fatal(e.Start(":8080"))
}
次に以下のコマンドを実行し、go.modの更新からDockerコンテナの再ビルドおよび再起動を行います。
$ docker compose exec api go mod tidy
$ docker compose down
$ docker compose build --no-cache
$ docker compose up -d
サンプルAPIを実行して試す
次に上記で作成したサンプルAPIをPostmanを使って試します。
まずは以下のリクエストボディを設定し、POSTメソッドで「http://localhost:8080/api/v1/redis/set」を実行します。
・リクエストボディ
{
"key": "name",
"value": "田中太郎",
"ttlSeconds": 0,
"mode": "create",
"keepTTL": false
}
実行後、下図のようにステータス200で想定通りの結果になればOKです。

次にGETメソッドで「http://localhost:8080/api/v1/redis/get/{対象データのkey}」を実行し、下図のようにステータス200で想定通りの結果になればOKです。

次に以下のリクエストボディを設定し、再度POSTメソッドで「http://localhost:8080/api/v1/redis/set」を実行します。
・リクエストボディ
{
"key": "name",
"value": "田中二郎",
"ttlSeconds": 0,
"mode": "update",
"keepTTL": false
}
実行後、下図のようにステータス200で想定通りの結果になればOKです。

次に再度GETメソッドで「http://localhost:8080/api/v1/redis/get/{対象データのkey}」を実行し、下図のようにステータス200で想定通りの結果になればOKです。

次にDELETEメソッドで「http://localhost:8080/api/v1/redis/del/{対象データのkey}」を実行し、下図のようにステータス204で想定通りの結果になればOKです。

次に再度GETメソッドで「http://localhost:8080/api/v1/redis/get/{対象データのkey}」を実行し、下図のようにステータス200で想定通りの結果になればOKです。

クラウドインフラのRedisのサービスについて
各種クラウドインフラにはRedisのサービスがありますが、Google Cloudなら「MemoryStore for Redis」、AWSなら「ElastiCache for Redis」になります。
それぞれのサービスについては、サポートしていない機能もあったりするため、使おうと思っている機能がサポートされているかは事前に確認して下さい。
最後に
今回はGo言語(Golang)でRedisの使い方についてまとめました。
サンプルAPIでは基本となるデータ型の文字列を操作する処理をご紹介しましたが、Redisでは他にも様々なデータ型を扱えます。
用途に応じて使う機能が変わるので、その点については適宜調べていただく必要がありますが、基本的な使い方についてまとめたので、興味がある方はぜひ参考にしてみて下さい。


コメント