👶
Redisの基本: 一般的なデータ型とベストプラクティス
Redis の一般的なデータ型
文字列(Strings)
Redis の文字列は基本的なデータ型であり、文字列値を保存および取得するために使用されます。
- ユースケース:テキストや数値の保存に適しており、例えばユーザーの名前、メールアドレス、ページカウンターなどに利用できます。また、バイナリデータの保存も可能なため、画像やシリアライズされたオブジェクトの格納にも使えます。
- メリット:操作が簡単で、インクリメント(INCR)などの原子操作を実行できます。
// 文字列を保存
let _: () = conn.set("username", "alice").await.unwrap();
// 文字列を取得
let username: String = conn.get("username").await.unwrap();
リスト(Lists)
Redis のリストは、文字列の集合であり、挿入順に並べられます。
- ユースケース:メッセージキュー、アクティビティログ、最近アクセスしたアイテムのリストなどの実装に適しています。リストは両端に要素を追加または削除できるため、スタックまたはキューとして使用できます。
- メリット:高速な挿入・削除が可能で、FIFO(先入れ先出し)キューや LIFO(後入れ先出し)スタックとして利用できます。
// リストの先頭に要素を追加
let _: () = conn.lpush("events", "login").await.unwrap();
let _: () = conn.lpush("events", "logout").await.unwrap();
// リストの要素を取得
let events: Vec<String> = conn.lrange("events", 0, -1).await.unwrap();
セット(Sets)
セットは、重複のない文字列の無秩序な集合です。
- ユースケース:タグ、アクセスした IP アドレス、ソーシャルネットワークの友達リストなど、順序を必要としない一意な要素の保存に使用されます。
- メリット:要素の追加、削除、存在チェックを高速に行え、さらに集合演算(和集合、積集合、差集合)を実行できます。
// セットに要素を追加
let _: () = conn.sadd("tags", "redis").await.unwrap();
let _: () = conn.sadd("tags", "database").await.unwrap();
// セットの全メンバーを取得
let tags: Vec<String> = conn.smembers("tags").await.unwrap();
ソート済みセット(Sorted Sets)
ソート済みセットは、セットに似ていますが、各メンバーにスコア(数値)が関連付けられます。
- ユースケース:ランキング、優先度キュー、スコア付きのデータの保存に適しています。
- メリット:セットの基本操作に加え、スコアや辞書順による要素の取得や範囲検索が可能です。
// ソート済みセットに要素を追加
let _: () = conn.zadd("leaderboard", "alice", 100).await.unwrap();
let _: () = conn.zadd("leaderboard", "bob", 200).await.unwrap();
// ソート済みセットの要素を取得
let leaderboard: Vec<(String, f64)> = conn.zrange_withscores("leaderboard", 0, -1).await.unwrap();
ハッシュ(Hashes)
ハッシュはキーと値のペアの集合であり、プログラミング言語の辞書やオブジェクトに似ています。
- ユースケース:ユーザー情報(名前、年齢、メールアドレスなど)の保存など、複数の関連データをまとめて管理するのに適しています。
- メリット:複数のフィールドを一度に読み書きでき、オブジェクトの表現やデータの集約に便利です。
// ハッシュにキーと値を追加
let _: () = conn.hset("user:100", "email", "alice@example.com").await.unwrap();
// ハッシュのすべてのキーと値を取得
let user_info: HashMap<String, String> = conn.hgetall("user:100").await.unwrap();
ビットマップ(Bitmaps)
ビットマップは、ビット単位で構成された配列で、各ビットは独立して設定または取得が可能です。
- ユースケース:ユーザーの出席状況、特定機能のオン/オフ状態など、存在の有無をマークする場面に適しています。
- メリット:非常に高い空間効率を持ち、大量のブール値データを扱うのに適しています。
// ビットマップでビットを設定
let _: () = conn.setbit("features", 0, true).await.unwrap(); // 機能0を有効にする
// ビットマップからビット値を取得
let feature_enabled: bool = conn.getbit("features", 0).await.unwrap();
ハイパーログログ(HyperLogLogs)
HyperLogLog は、集合の基数(ユニークな要素の数)を効率的に推定する確率的データ構造です。
- ユースケース:ウェブサイトのユニークビジター数など、大規模データのユニーク要素数の推定に適しています。
- メリット:伝統的なカウント方法と比較してメモリ使用量が少なく、大規模データ処理に適しています。
// HyperLogLog に要素を追加
let _: () = conn.pfadd("pageviews", "user1").await.unwrap();
let _: () = conn.pfadd("pageviews", "user2").await.unwrap();
// 推定基数を取得
let unique_pageviews: i64 = conn.pfcount("pageviews").await.unwrap();
データ型の選択
バックエンド業務で最適な Redis データ型を選択するためには、自身のデータ構造とユースケースを理解することが重要です。以下は、一般的なバックエンドシナリオと推奨される Redis データ型の例です。
ユーザーセッション(User Sessions)
- 推奨データ型:ハッシュ(Hash)
- 理由:ハッシュは、ユーザー ID、トークン、最終アクセス日時など、セッションオブジェクトの複数の属性を格納でき、特定のフィールドを個別に更新または取得できます。
let _: () = conn.hset("session:userid", "token", "abc123").await.unwrap();
let _: () = conn.hset("session:userid", "last_access", "2023-01-01").await.unwrap();
リアルタイムメッセージングまたはイベントキューイング(Real-time Messaging or Event Queuing)
- 推奨データ型:リスト(List)
- 理由:リストは FIFO キューとして動作し、リアルタイムのメッセージ処理やタスクキューに適しています。
let _: () = conn.rpush("events_queue", "event1").await.unwrap();
let event: String = conn.lpop("events_queue").await.unwrap();
アクセスカウンターまたはレート制限(Access Counters or Rate Limiting)
- 推奨データ型:文字列(String)
- 理由:文字列型は原子操作によるインクリメントをサポートし、カウンターとしての使用に適しています。
let _: () = conn.incr("page_view_count", 1).await.unwrap();
let count: i64 = conn.get("page_view_count").await.unwrap();
ランキングまたはスコアソーティング(Leaderboards or Score Sorting)
- 推奨データ型:ソート済みセット(Sorted Set)
- 理由:スコアによる自動ソートが可能で、ランキングなどスコア順のデータに最適です。
let _: () = conn.zadd("leaderboard", "user123", 2500).await.unwrap();
let leaderboard: Vec<(String, f64)> = conn.zrange_withscores("leaderboard", 0, -1).await.unwrap();
ユニーク値のコレクション(タグやカテゴリなど)(Unique Value Collections like Tags or Categories)
- 推奨データ型:セット(Set)
- 理由:重複のないデータの保存に適しており、タグの管理などに便利です。
let _: () = conn.sadd("tags", "redis").await.unwrap();
let tags: Vec<String> = conn.smembers("tags").await.unwrap();
複数属性のオブジェクト保存(Multi-attribute Object Storage)
- 推奨データ型:ハッシュ(Hash)
- 理由:複数の属性を個別に管理でき、オブジェクトの保存に便利です。
let _: () = conn.hset("user:100", "name", "Alice").await.unwrap();
let user: HashMap<String, String> = conn.hgetall("user:100").await.unwrap();
機能フラグまたはトグル(Feature Flags or Toggles)
- 推奨データ型:ビットマップ(Bitmap)
- 理由:機能のオン/オフなど、ブール値の保存に適しています。
let _: () = conn.setbit("features", 1, true).await.unwrap();
let feature_on: bool = conn.getbit("features", 1).await.unwrap();
最適なデータ型の選択は、具体的なニーズに依存します。単純なキーと値のペアであれば文字列型が適していますが、ユーザープロファイルやセッション情報のように複数のフィールドを持つ場合はハッシュ型が便利です。ランキングやスコア順のデータ管理が必要であれば、ソート済みセットが最適です。
それぞれのユースケースに応じた最適なデータ型を選択し、効率的なデータ管理を行いましょう。
私たちはLeapcell、バックエンド・プロジェクトのホスティングの最適解です、組み込みのサーバーレスRedisを搭載しています。
Leapcellは、Webホスティング、非同期タスク、Redis向けの次世代サーバーレスプラットフォームです:
複数言語サポート
- Node.js、Python、Go、Rustで開発できます。
無制限のプロジェクトデプロイ
- 使用量に応じて料金を支払い、リクエストがなければ料金は発生しません。
比類のないコスト効率
- 使用量に応じた支払い、アイドル時間は課金されません。
- 例: $25で6.94Mリクエスト、平均応答時間60ms。
洗練された開発者体験
- 直感的なUIで簡単に設定できます。
- 完全自動化されたCI/CDパイプラインとGitOps統合。
- 実行可能なインサイトのためのリアルタイムのメトリクスとログ。
簡単なスケーラビリティと高パフォーマンス
- 高い同時実行性を容易に処理するためのオートスケーリング。
- ゼロ運用オーバーヘッド — 構築に集中できます。
Xでフォローする:@LeapcellHQ
Discussion