Redis Sorted Sets(パート1)

Sorted Setはスコアを持つセットで、要素はスコアでソートされます。このレッスンでは、基本的なソート済みセット操作について解説します。

Sorted Setとは

Sorted Setの特徴:

leaderboard
├─ "player1" → score: 100
├─ "player2" → score: 200
├─ "player3" → score: 300
└─ "player4" → score: 400
💡 内部実装: Sorted Setはスキップリスト+ハッシュテーブルを使用しています。スキップリストは効率的なソートと範囲クエリをサポートし、ハッシュテーブルは高速なスコア検索を可能にします。

ZADD:要素の追加

基本的な使用方法

REDIS
# 単一の要素を追加
ZADD leaderboard 100 "player1"
(integer) 1  # 新しく追加された要素の数を返す

# 複数の要素を追加
ZADD leaderboard 200 "player2" 300 "player3" 400 "player4"
(integer) 3

ZADDのパラメータ

REDIS
# NX:新しい要素のみ追加、既存のものは更新しない
ZADD leaderboard NX 150 "player1"
(integer) 0  # player1は既に存在、更新されない

# XX:既存の要素のみ更新、新しいものは追加しない
ZADD leaderboard XX 500 "player5"
(integer) 0  # player5は存在しない、追加されない

# CH:変更された要素の数を返す(更新を含む)
ZADD leaderboard CH 120 "player1"
(integer) 1  # player1のスコアを更新

# INCR:スコアを増加(ZINCRBYと同等)
ZADD leaderboard INCR 50 "player1"
"170"  # 新しいスコアを返す

既存要素のスコア更新

REDIS
# 要素が既に存在する場合、スコアが更新される
ZADD leaderboard 250 "player1"

# 新しいスコアを表示
ZSCORE leaderboard "player1"
"250"

ZSCORE:要素のスコアを取得

REDIS
ZADD leaderboard 100 "player1" 200 "player2"

# スコアを取得
ZSCORE leaderboard "player1"
"100"

# 要素が存在しない場合
ZSCORE leaderboard "notexist"
(nil)

ZRANKとZREVRANK:ランクを取得

ZRANK:低い方からのランク

REDIS
ZADD leaderboard 100 "player1" 200 "player2" 300 "player3"

# ランクは0から始まる
ZRANK leaderboard "player1"
(integer) 0  # 1位(最も低いスコア)

ZRANK leaderboard "player2"
(integer) 1  # 2位

ZRANK leaderboard "player3"
(integer) 2  # 3位

ZREVRANK:高い方からのランク

REDIS
# 高い方からのランク(最も高いスコアがランク0)
ZREVRANK leaderboard "player3"
(integer) 0  # 1位(最も高いスコア)

ZREVRANK leaderboard "player2"
(integer) 1  # 2位

ZREVRANK leaderboard "player1"
(integer) 2  # 3位
💡 ランクルール:

  • ZRANK:低いスコアから高いスコアへ、最も低いスコアがランク0
  • ZREVRANK:高いスコアから低いスコアへ、最も高いスコアがランク0
  • ランクは0から始まり、1位のランクは0

ZRANGEとZREVRANGE:ランク範囲で要素を取得

ZRANGE:ランク範囲で取得(低い方から)

REDIS
ZADD leaderboard 100 "player1" 200 "player2" 300 "player3" 400 "player4"

# すべての要素を取得
ZRANGE leaderboard 0 -1
1) "player1"
2) "player2"
3) "player3"
4) "player4"

# 最初の2要素を取得
ZRANGE leaderboard 0 1
1) "player1"
2) "player2"

# 最後の2要素を取得
ZRANGE leaderboard -2 -1
1) "player3"
2) "player4"

# スコア付きで要素を取得
ZRANGE leaderboard 0 -1 WITHSCORES
1) "player1"
2) "100"
3) "player2"
4) "200"
5) "player3"
6) "300"
7) "player4"
8) "400"

ZREVRANGE:ランク範囲で取得(高い方から)

REDIS
# 高い方からすべての要素を取得
ZREVRANGE leaderboard 0 -1 WITHSCORES
1) "player4"
2) "400"
3) "player3"
4) "300"
5) "player2"
6) "200"
7) "player1"
8) "100"

# トップ3を取得(最も高いスコア)
ZREVRANGE leaderboard 0 2 WITHSCORES
1) "player4"
2) "400"
3) "player3"
4) "300"
5) "player2"
6) "200"

ZCARD:要素数を取得

REDIS
ZADD leaderboard 100 "player1" 200 "player2" 300 "player3"

ZCARD leaderboard
(integer) 3

ZCOUNT:スコア範囲内の要素をカウント

REDIS
ZADD leaderboard 100 "player1" 150 "player2" 200 "player3" 250 "player4" 300 "player5"

# スコアが150〜250の要素をカウント
ZCOUNT leaderboard 150 250
(integer) 3  # player2、player3、player4

# -inf と +inf を使用
ZCOUNT leaderboard -inf +inf
(integer) 5  # すべての要素

ZREM:要素の削除

REDIS
ZADD leaderboard 100 "player1" 200 "player2" 300 "player3"

# 単一の要素を削除
ZREM leaderboard "player1"
(integer) 1

# 複数の要素を削除
ZREM leaderboard "player2" "player3"
(integer) 2

# 存在しない要素を削除
ZREM leaderboard "notexist"
(integer) 0

ZINCRBY:スコアの増加

REDIS
ZADD leaderboard 100 "player1"

# スコアを50増加
ZINCRBY leaderboard 50 "player1"
"150"  # 新しいスコアを返す

# スコアを減少(負の数を渡す)
ZINCRBY leaderboard -20 "player1"
"130"

Sorted Setのユースケース

ユースケース1:ゲームリーダーボード

REDIS
# プレイヤーのスコアを更新
ZADD game:leaderboard 1500 "player:123"
ZADD game:leaderboard 2300 "player:456"
ZADD game:leaderboard 1800 "player:789"

# トップ10を取得
ZREVRANGE game:leaderboard 0 9 WITHSCORES

# プレイヤーのランクを取得
ZREVRANK game:leaderboard "player:123"

# プレイヤーのスコアを増加
ZINCRBY game:leaderboard 100 "player:123"

ユースケース2:トレンド検索

REDIS
# トレンドの熱度スコアを更新
ZADD hot:search 10000 "Redis tutorial"
ZADD hot:search 8000 "Python basics"
ZADD hot:search 15000 "JavaScript"

# トップ10のトレンドを取得
ZREVRANGE hot:search 0 9 WITHSCORES

# 熱度スコアを増加
ZINCRBY hot:search 100 "Redis tutorial"

ユースケース3:遅延キュー

REDIS
# 遅延タスクを追加(スコアは実行タイムスタンプ)
ZADD delay:queue 1719129600 "task:1"  # 2024-06-23 10:00:00
ZADD delay:queue 1719133200 "task:2"  # 2024-06-23 11:00:00

# 現在時刻より前のタスクを取得(実行すべきタスク)
ZRANGEBYSCORE delay:queue -inf 1719129600

ユースケース4:重み付きタグ

REDIS
# ユーザーの興味タグ(スコアは興味レベル)
ZADD user:1:interests 100 "redis"
ZADD user:1:interests 80 "database"
ZADD user:1:interests 60 "cache"

# ユーザーの最も興味があるタグを取得
ZREVRANGE user:1:interests 0 4 WITHSCORES

ユースケース5:試験ランキング

REDIS
# 学生のスコア
ZADD exam:math 95 "student:1"
ZADD exam:math 88 "student:2"
ZADD exam:math 92 "student:3"

# スコアランキングを取得
ZREVRANGE exam:math 0 -1 WITHSCORES

# 学生のランクを取得
ZREVRANK exam:math "student:1"

Sorted Setのエンコーディング最適化

Redisはソート済みセットのサイズに基づいてエンコーディングを自動的に選択します:

エンコーディング 条件 説明
ziplist 要素 <= 128、要素の長さ <= 64バイト 圧縮リスト、メモリ節約
skiplist 要素 > 128 または 要素の長さ > 64バイト スキップリスト + ハッシュテーブル、パフォーマンス向上

エンコーディングタイプの確認

REDIS
ZADD small:zset 1 "a" 2 "b" 3 "c"
OBJECT ENCODING small:zset
"ziplist"

# 多くの要素を追加した後
OBJECT ENCODING large:zset
"skiplist"

❓ よくある質問

Q Sorted SetとSetの違いは何ですか?
A Sorted Setのすべての要素はスコアを持ち、それでソートされます。Setは順序がありません。Sorted Setはリーダーボードやランキングのシナリオに最適です。
Q スコアは小数にできますか?
A はい。スコアは倍精度浮動小数点数で、小数をサポートします。
Q ZRANKはランクを0から返しますか、1から返しますか?
A 0からです。1位のランクは0、2位のランクは1です。
Q 最も高いスコアを持つ要素を取得するにはどうすればよいですか?
A ZREVRANGE key 0 0 または ZRANGE key -1 -1 を使用します。
Q 要素は重複できますか?
A いいえ。要素は一意ですが、スコアは重複可能です。

📖 まとめ

📝 練習問題

  1. リーダーボード: Sorted Setを使用してゲームリーダーボードを実装し、スコアを更新、ランクを表示、トップ10を取得しましょう
  2. トレンドリスト: トレンド検索リストを実装し、熱度スコアを更新、トレンドを表示、熱度を増加しましょう
  3. 試験ランキング: 学生のスコアをSorted Setに保存し、ランキングとスコアを表示しましょう
  4. 遅延キュー: Sorted Setを使用して遅延タスクキューを実装し、タスクを追加、期限切れのタスクを取得しましょう

次のレッスン

次のレッスンでは、Redis Sorted Sets(パート2)について学びます。高度なソート済みセット操作を解説します。

100%