1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Hands-Onで学ぶ、はじめてのRedis

Last updated at Posted at 2025-05-30

Redis Hands-On

1. 事前準備

1.1. Redisコンテナーの起動 (初回起動の場合)

shell
docker run -d --name redis-test -p 6379:6379 redis:latest

1.2. Redisコンテナーの起動 (前回起動した同じコンテナーを利用する場合)

shell
! docker start redis-test

1.3. Hands-On前にRedisの中身をクリーニングする

以下をnotebookのセルで実行

notebook
r.flushdb()
output
True

2. Redisの基本動作の確認

2.1. 文字列操作: キーバリューの設定/取得/上書きの動作の確認

Redisの基本的なキーバリューの「設定 (Set)」「取得 (Get)」「上書き」の動作を確認する

  • set:
    • language という名前のキーに、最初に Python という値を設定
    • language キーの値を 'Rust' に上書きも可能
  • get:
    • 設定した値の読み出し
notebook
import redis
r = redis.Redis(host='localhost', port=6379, db=0)

# SetとGet
r.set('language', 'Python')
print(r.get('language').decode())  # → Python

# 文字列の上書き
r.set('language', 'Rust')
print(r.get('language').decode())  # → Rust
output
Python
Rust

2.2. List: リストにデータを順番に格納/取り出しの実施

  • lpush:
    • fruits という名前の「順番付きのデータ入れ(リスト)」を用意する
    • そのリストの先頭に apple、次に banana、最後に orange を順番に押し込んでいく
    • 結果、リストの中は先頭から ['orange', 'banana', 'apple'] という並びになる
  • lrange:
    • fruitsリストの中身を最初から最後まで全部取り出して画面に表示する
    • 0は最初の要素
    • -1は最後の要素という意味
notebook
# LPUSHでリストに値を追加
r.lpush('fruits', 'apple', 'banana', 'orange')

# LRANGEで全要素を取得(0から-1まで)
print(r.lrange('fruits', 0, -1))  # → [b'orange', b'banana', b'apple']
output
[b'orange', b'banana', b'apple']

2.3. Set: セット型データを使って重複させたくないデータを管理

  • sadd:
    • colors という名前の「順番がなく、同じものは入らない特別な袋(セット)」を用意
    • その袋に red, blue, green という色と、もう一度 red を入れようとする
    • でも、同じものは入らないルールなので、袋の中には red, blue, green がそれぞれ1つずつだけ入るはず
  • smembers:
    • colors 袋の中身を全部(順番は気にせず)取り出して、画面に表示する
    • このとき重複がなく、各要素はユニークとなっている
notebook
# SADDでセットに追加(重複は無視される)
r.sadd('colors', 'red', 'blue', 'green', 'red')

# SMEMBERSですべて取得(順不同)
print(r.smembers('colors'))  # → {b'red', b'green', b'blue'}
output
{b'blue', b'red', b'green'}

2.4. Hash: 1つのハッシュに複数の情報を項目ごとに整理して保存できる

  • hset:
    • user:1 という名前の「プロフィールカード(ハッシュ)」を用意する
    • そのカードに、nameという項目にはAliceageという項目には30と書き込む
  • hget:
    • 次に、そのカードからnameの項目だけを取り出して表示する(→ Aliceと表示される)
  • hgetall:
    • 最後に、そのカードに書かれている「すべての項目とその内容」をまとめて取り出して表示する
notebook
# HSETでフィールドをセット
r.hset('user:1', mapping={'name': 'Alice', 'age': 30})

# HGETで1つのフィールドを取得
print(r.hget('user:1', 'name').decode())  # → Alice

# HGETALLで全フィールド取得
print(r.hgetall('user:1'))  # → {b'name': b'Alice', b'age': b'30'}
output
Alice
{b'name': b'Alice', b'age': b'30'}

2.5. Sorted Set: 値が低い順もしくは高い順にデータを取り出し

  • zadd:
    • ranking という名前の「得点付きランキングボード(ソート済みセット)」を作る
    • ランキングボードに、「Aliceさんは100点」「Bobさんは150点」「Carolさんは120点」と登録する
    • Redisが内部で自動的にスコアの低い順に並べ替える準備をしてくれる
  • zrange:
    • ランキングボードのメンバー全員を、スコアが低い順に、もしくはスコアが高い順にスコアといっしょに取り出して画面に表示する
    • スコアが高い順にする場合は引数に desc=True を用いる
notebook
# ZADDでスコア付きデータ追加
r.zadd('ranking', {'Alice': 100, 'Bob': 150, 'Carol': 120})

# ZRANGEでソートされた順に取得(withscores=Trueでスコア付き)
print(r.zrange('ranking', 0, -1, withscores=True))
# → [(b'Alice', 100.0), (b'Carol', 120.0), (b'Bob', 150.0)]

# ZRANGEでソートされた逆順に取得(withscores=Trueでスコア付き, desc=Trueで逆順)
print(r.zrange('ranking', 0, -1, withscores=True, desc=True))
# → [(b'Alice', 100.0), (b'Carol', 120.0), (b'Bob', 150.0)]
output
[(b'Alice', 100.0), (b'Carol', 120.0), (b'Bob', 150.0)]
[(b'Bob', 150.0), (b'Carol', 120.0), (b'Alice', 100.0)]

3. Listを使ったTodoリストの応用例

念のため環境のクリーン

notebook
r.flushdb()

3.1. 新しいタスクを追加(LPUSH

notebook
import redis
r = redis.Redis(host='localhost', port=6379, db=0)
# 新しいタスクを追加
r.lpush('todo', '買い物に行く', 'メール返信', 'Redisを学ぶ')

3.2. タスク一覧を表示(LRANGE

notebook
# 現在のタスク一覧
print('Todoリスト:')
for task in r.lrange('todo', 0, -1):
    print('-', task.decode())
output
Todoリスト:
- Redisを学ぶ
- メール返信
- 買い物に行く

3.3. 完了したタスクを削除(RPOP

  • LPUSHでタスクを追加した場合、RPOP は「一番古い情報(最初に追加されたタスク)」を取り出すことになる
  • これは、お店の行列と同じで、「最初に来た人 (First-In) が最初にサービスを受ける (First-Out)」なので、FIFO(ファイフォ)キューとなる
notebook
# タスクを完了(末尾から削除)
done = r.rpop('todo')
print('完了タスク:', done.decode())
output
完了タスク: 買い物に行く

3.4. 削除確認

notebook
# 更新後のタスク一覧
print('更新後のTodoリスト:')
for task in r.lrange('todo', 0, -1):
    print('-', task.decode())

買い物に行くが削除されていることを確認

output
更新後のTodoリスト:
- Redisを学ぶ
- メール返信

4. ユーザー情報を管理(Hash)

念のためRedisの初期化を実施

notebook
r.flushdb()

4.1. ユーザー情報(名前、年齢、メール)を登録(HSET

notebook
import redis

r = redis.Redis(host='localhost', port=6379, db=0)

# ユーザー情報の登録
user_id = 'user:1001'
r.hset(user_id, mapping={
    'name': 'Taro',
    'age': '25',
    'email': 'taro@example.com'
})

4.2. 個別の情報取得(HGET

notebook
# 個別に取得
print('名前:', r.hget(user_id, 'name').decode())
output
名前: Taro

4.3. 全情報取得(HGETALL

notebook
# すべて取得
print('ユーザー情報:')
for key, value in r.hgetall(user_id).items():
    print(f"{key.decode()}: {value.decode()}")
output
ユーザー情報:
name: Taro
age: 25
email: taro@example.com

4.3. RedisInsightでの内容確認

image.png

5. 人気ランキング(Sorted Set)

5.1. ユーザーのスコアを追加(ZADD

notebook
import redis

r = redis.Redis(host='localhost', port=6379, db=0)

# スコアを追加(スコアは数値)
r.zadd('ranking', {
    'Taro': 150,
    'Hanako': 180,
    'Ken': 120
})

5.2. ランキング表示(ZRANGE

notebook
# ランキング表示(スコア付き)
print('人気ランキング:')
for name, score in r.zrange('ranking', 0, -1, withscores=True):
    print(f"{name.decode()}: {int(score)}")
output
人気ランキング:
Ken: 120
Taro: 150
Hanako: 180

6. Redis Pub/Sub とは?

Pub/Subの意味

  • Publisher: メッセージを「チャンネル」に送る人(例:通知を送る側)
  • Subscriber: チャンネルを購読してメッセージを受け取る人(例:通知を受け取る側)

応用例

  • Flask + WebSocket + Redis でチャットアプリのバックエンドに
  • ログ監視やイベント通知システムに活用
  • IoT デバイスのイベント通知にもよく使われます

6.1. Subscriber(受け取る側)のコードを保存する

以下の内容を subscriber.py という名前で保存する

subscriber.py
import redis

r = redis.Redis(host='localhost', port=6379, db=0)
pubsub = r.pubsub()

# 'news' チャンネルを購読
pubsub.subscribe('news')
print("チャンネル 'news' を購読中...")

for message in pubsub.listen():
    if message['type'] == 'message':
        print("受信:", message['data'].decode())

6.2. Publisher(送る側)

以下の内容を publisher.py という名前で保存する

publisher.py
import redis
import time

r = redis.Redis(host='localhost', port=6379, db=0)

messages = [
    "Redisの練習を始めよう!",
    "新しいタスクが追加されました",
    "通知:サーバーが起動しました",
]

for msg in messages:
    r.publish('news', msg)
    print("送信:", msg)
    time.sleep(1)

6.3. terminal1を開いて、以下のコマンドを実行する

$ python subscriber.py
チャンネル 'news' を購読中...

6.4. terminal2を開いて、以下のコマンドを実行する

$ python publisher.py
送信: Redisの練習を始めよう!
送信: 新しいタスクが追加されました
送信: 通知:サーバーが起動しました

6.5. terminal1の表示を観察する

受信: Redisの練習を始めよう!
受信: 新しいタスクが追加されました
受信: 通知:サーバーが起動しました

7. Clean Up

6.1. Redisコンテナーの停止

terminal
docker stop redis-test
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?