Redis: Redis Sorted Sets(パート1)

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

1. Sorted Setとは

Sorted Setの特徴:

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


2. ZADD:要素の追加

(1) 基本的な使用方法

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

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

(2) 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"  # 新しいスコアを返す

(3) 既存要素のスコア更新

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

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

3. ZSCORE:要素のスコアを取得

REDIS
ZADD leaderboard 100 "player1" 200 "player2"

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

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

4. ZRANKとZREVRANK:ランクを取得

(1) 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位

(2) 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

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

(1) 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"

(2) 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"

6. ZCARD:要素数を取得

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

ZCARD leaderboard
(integer) 3

7. 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  # すべての要素

8. 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

9. ZINCRBY:スコアの増加

REDIS
ZADD leaderboard 100 "player1"

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

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

10. Sorted Setのユースケース

(1) ユースケース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) ユースケース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) ユースケース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) ユースケース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) ユースケース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"

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

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

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

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

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

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

▶ サンプル

ソート済みセットの基本操作:

BASH
127.0.0.1:6379> ZADD leaderboard 100 "Alice" 200 "Bob" 150 "Charlie"
(integer) 3
127.0.0.1:6379> ZRANGE leaderboard 0 -1 WITHSCORES
1) "Alice"
2) "100"
3) "Charlie"
4) "150"
5) "Bob"
6) "200"

❓ よくある質問

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を使用して遅延タスクキューを実装し、タスクを追加、期限切れのタスクを取得しましょう

12. 次のレッスン

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

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%