Redis Strings(パート2)
このレッスンでは、文字列の数値演算とビット演算について解説します。カウンターや統計などのユースケースを実現できます。
数値演算
Redisの文字列は整数を保存でき、アトミックな数値演算をサポートします。
INCRとDECR:インクリメントとデクリメント
REDIS
# 初期値を設定
SET counter 10
# 1増加
INCR counter
(integer) 11
# 1減少
DECR counter
(integer) 10
💡 アトミック性: INCRとDECRはアトミックな操作です。複数のクライアントが同時にINCRを実行しても競合が発生しないため、カウンターに最適です。
INCRBYとDECRBY:増加量を指定
REDIS
SET counter 100
# 10増加
INCRBY counter 10
(integer) 110
# 20減少
DECRBY counter 20
(integer) 90
INCRBYFLOAT:浮動小数点演算
REDIS
SET price 10.5
# 2.3増加
INCRBYFLOAT price 2.3
"12.8"
# 1.5減少(負の数を渡す)
INCRBYFLOAT price -1.5
"11.3"
⚠️ 補足: INCRBYFLOATは浮動小数点数を文字列形式で返します。整数ではありません。
数値演算の制限
REDIS
# 数値以外の文字列に対する操作は失敗
SET text "hello"
INCR text
(error) ERR value is not an integer or out of range
# 存在しないキーに対する操作(0から開始)
INCR newcounter
(integer) 1 # 0から1に増加
使用例:カウンター
REDIS
# 記事の閲覧数
INCR article:123:views
(integer) 1
# ユーザーのいいね数
INCR user:456:likes
(integer) 1
# API呼び出し数
INCR api:usage:20260623
(integer) 1
範囲操作
GETRANGE:部分文字列を取得
REDIS
SET message "Hello Redis World"
# 最初の5文字を取得
GETRANGE message 0 4
"Hello"
# 中間部分を取得
GETRANGE message 6 10
"Redis"
# 最後の5文字を取得
GETRANGE message -5 -1
"World"
# 文字列全体を取得
GETRANGE message 0 -1
"Hello Redis World"
💡 インデックスルール:
- インデックスは0から始まります
- 終了位置は含まれます
- 負のインデックスは末尾からカウントします(-1は最後の文字)
SETRANGE:部分文字列を置換
REDIS
SET message "Hello World"
# 位置6から置換
SETRANGE message 6 "Redis"
(integer) 11 # 文字列の長さを返す
GET message
"Hello Redis"
# 元の長さを超えて置換(自動的に埋められる)
SET short "Hi"
SETRANGE short 5 "There"
(integer) 10
GET short
"Hi\x00\x00\x00There" # 間にnullバイトで埋められる
⚠️ 補足: SETRANGEが元の文字列の長さを超える場合、隙間はnullバイト(\x00)で埋められます。
ビット操作
Redisの文字列はビット操作をサポートしており、ブルームフィルターやビットマップ統計などに役立ちます。
SETBITとGETBIT:ビットの設定と取得
REDIS
# ビットマップを設定(初期はすべて0)
SETBIT mybitmap 0 1
(integer) 0 # 古い値を返す
SETBIT mybitmap 2 1
(integer) 0
SETBIT mybitmap 7 1
(integer) 0
# ビット値を取得
GETBIT mybitmap 0
(integer) 1
GETBIT mybitmap 1
(integer) 0
GETBIT mybitmap 2
(integer) 1
BITCOUNT:1に設定されたビットをカウント
REDIS
# すべてのビットをカウント
BITCOUNT mybitmap
(integer) 3 # 3ビットが1に設定されている
# バイト範囲内でカウント
BITCOUNT mybitmap 0 0
(integer) 3 # バイト0には3ビットが1に設定されている
BITOP:ビット演算
REDIS
# 2つのビットマップを作成
SETBIT bitmap1 0 1
SETBIT bitmap1 1 1
SETBIT bitmap2 1 1
SETBIT bitmap2 2 1
# AND
BITOP AND result bitmap1 bitmap2
(integer) 1
GETBIT result 1
(integer) 1 # 両方でビット1のみが1
# OR
BITOP OR result bitmap1 bitmap2
(integer) 1
# XOR
BITOP XOR result bitmap1 bitmap2
(integer) 1
# NOT(1つのキーのみサポート)
BITOP NOT result bitmap1
(integer) 1
BITPOS:最初の0または1の位置を検索
REDIS
SET mykey "\xff\xf0\x00" # バイナリ:11111111 11110000 00000000
# 最初の0を検索
BITPOS mykey 0
(integer) 12 # ビット12が最初の0
# 最初の1を検索
BITPOS mykey 1
(integer) 0 # ビット0が最初の1
# バイト範囲内で検索
BITPOS mykey 1 1 2
(integer) 8 # バイト1-2内で、ビット8が最初の1
使用例:ユーザーのチェックイン
REDIS
# ユーザーID 123が2026年6月23日にチェックイン(年の174日目)
SETBIT user:123:signin:2026 174 1
# チェックイン済みか確認
GETBIT user:123:signin:2026 174
(integer) 1
# 年間の合計チェックイン数をカウント
BITCOUNT user:123:signin:2026
(integer) 50 # 50日間チェックイン
# 連続チェックインの確認(BITPOSとビジネスロジックが必要)
使用例:オンラインユーザー統計
REDIS
# ユーザー123がオンライン
SETBIT online:users 123 1
# ユーザー456がオンライン
SETBIT online:users 456 1
# オンラインユーザー数をカウント
BITCOUNT online:users
(integer) 2
# ユーザー123がオフライン
SETBIT online:users 123 0
実用的なStringのヒント
1. 一意なIDの生成
REDIS
# INCRを使用して自動インクリメントIDを生成
SET next:user:id 1000
INCR next:user:id
(integer) 1001 # 新しいユーザーID
INCR next:user:id
(integer) 1002
2. レート制限カウンター
REDIS
# APIレート制限:1分間に最大100回
SET limit:api:user:1 0 EX 60
INCR limit:api:user:1
(integer) 1
# 制限を超えたか確認
GET limit:api:user:1
"50" # 現在50回呼び出し
3. 分散シーケンス番号
REDIS
# 注文番号の生成
SET order:sequence 1000000000
INCR order:sequence
(integer) 1000000001 # 新しい注文番号
4. UV(ユニークビジター)統計
REDIS
# ビットマップを使用したUV統計
SETBIT uv:20260623 12345 1 # ユーザーID 12345が訪問
SETBIT uv:20260623 67890 1 # ユーザーID 67890が訪問
# UVをカウント
BITCOUNT uv:20260623
(integer) 2 # 2人のユニークビジター
パフォーマンス最適化のヒント
1. バッチ操作の使用
REDIS
# ❌ 複数の個別操作
SET key1 "value1"
SET key2 "value2"
SET key3 "value3"
# ✅ バッチ操作
MSET key1 "value1" key2 "value2" key3 "value3"
2. 適切な有効期限の設定
REDIS
# キャッシュデータに有効期限を設定
SET cache:key "value" EX 3600
# キャッシュ雪崩を回避:TTLにランダムなジッターを追加
SET cache:key "value" EX 3600
3. 適切なエンコーディングの選択
REDIS
# 短い文字列はembstrエンコーディングを使用(<= 44バイト)
SET short "Hello Redis"
# 長い文字列はrawエンコーディングを使用
SET long "This is a very long string..."
# エンコーディングを確認
OBJECT ENCODING short
"embstr"
❓ よくある質問
Q INCRはオーバーフローしますか?
A はい。Redisの整数は64ビットの符号付き整数です(範囲:-2^63 〜 2^63-1)。範囲外になるとエラーが返ります。
Q 浮動小数点カウンターを実装するにはどうすればよいですか?
A INCRBYFLOATコマンドを使用しますが、文字列形式を返すことに注意してください。
Q ビット操作の実用的な用途は何ですか?
A ビットマップは、ユーザーのチェックイン、オンラインユーザー統計、ブルームフィルター、権限ビットなどに使用できます。非常にメモリ効率が良いです。
Q GETRANGEの時間複雑度は?
A O(N)で、Nは返される部分文字列の長さです。短い部分文字列の取得は非常に高速です。
Q 大きなテキスト(記事の内容など)を保存するにはどうすればよいですか?
A まず圧縮するか、シャーディングすることを検討してください。より良い方法は、ファイルシステムやオブジェクトストレージに保存し、RedisにはURLのみを保持することです。
📖 まとめ
- INCR/DECRのアトミックなインクリメントとデクリメント、カウンターに最適
- INCRBY/DECRBYでカスタム増加量、INCRBYFLOATで浮動小数点
- GETRANGE/SETRANGEの範囲操作、負のインデックスをサポート
- SETBIT/GETBITのビット操作、ビットマップ統計に有用
- BITCOUNTで1に設定されたビットをカウント、BITOPでビット演算
- ビットマップの応用:ユーザーチェックイン、オンラインユーザー、UV統計
- 数値演算:カウンター、レート制限、一意なID生成
📝 練習問題
- カウンター: 記事の閲覧カウンターを実装し、10回の閲覧をシミュレートして最終カウントを確認しましょう
- 範囲操作: 長い文字列を設定し、GETRANGEを使用して異なる部分を取得しましょう
- ビットマップチェックイン: ビットマップを使用してユーザーのチェックインを実装し、チェックイン日数をカウントしましょう
- UV統計: ビットマップを使用してWebサイトのUVを追跡し、複数のユーザー訪問をシミュレートしましょう
次のレッスン
次のレッスンでは、Redis Hashes(パート1)について学びます。基本的なハッシュ操作を解説します。



