SET session:123 "user_data"
HSET user:1000 name "田中" age "30"
SADD team:dev "user:1000" "user:1001"
ZADD scores 100 "user:1000"
users:1000
のようなキー設計でエンティティ(実体)を表現することができるdepartment:営業部
のようなセットで検索用インデックス(索引)を実現することができる<エンティティ名>:<ID>:<属性>
の形式で一意性を確保する<インデックス名>:<値>
の形式で検索効率を向上させるtemp:<データ種別>:<ID>
の形式で一時データを管理する# Cache-Aside Pattern(キャッシュサイドパターン:データの効率的な読み書き方式)
def get_data(key):
cache = redis.get(key)
if not cache:
data = db.query(key) # メインDBから取得
redis.setex(key, 3600, data) # 1時間のTTL(Time To Live:生存時間)で保存
return cache
# トランザクション(不可分な処理のまとまり)を使用した更新
pipe = redis.pipeline()
pipe.hset("users:1000", "department", "技術部") # ユーザーの部署を更新
pipe.srem("department:営業部", "1000") # 旧所属からの削除
pipe.sadd("department:技術部", "1000") # 新所属への追加
pipe.execute() # トランザクションの実行
EXPIRE users:1000 3600
SCAN
コマンドを使用した期限切れキーの削除によりメモリを最適化する# インデックス作成
FT.CREATE users:index ON HASH PREFIX 1 users:
SCHEMA name TEXT age NUMERIC department TEXT
# 複合条件での検索(部署が技術部かつ年齢が20から30の範囲)
FT.SEARCH users:index "@department:技術部 @age:[20 30]"
これらの実装パターンは,アプリケーションの要件に応じて適切に組み合わせることで,高速で信頼性の高いシステムを構築することが可能である.
学習目標と内容
既存データベースのRedisでの操作方法を習得し,データ構造とインデックスの実装技術を理解する.
環境設定と準備作業
Redisのインストール手順(Ubuntu環境)では,ターミナルで以下のコマンドを実行する.
sudo apt -y install redis-server
Redisコマンドラインの起動と基本操作
起動手順:redis-cli
コマンドを実行することでRedisのコマンドラインインターフェースを起動する.
ヘルプ機能の利用方法:help
コマンドを実行すると,利用可能な全てのコマンドと機能の一覧が表示される.
終了手順:exit
コマンドを実行することで,セッションを安全に終了することができる.
データの挿入手順
ここではorder_records(注文記録)データを登録する.Hash(ハッシュ型)を使用して構造化データを格納する.
【説明】HashデータモデルによるレコードのRDB(リレーショナルデータベース)相当の永続化を行う.HMSETを使用してフィールドと値のペアを一括設定する.ISO8601形式のタイムスタンプを使用した時刻管理を実施する.データの一貫性はアプリケーション層で担保する.
【補足:基本的なデータ構造】
SET session:123 "user_data"
HSET user:1000 name "田中" age "30"
SADD team:dev "user:1000" "user:1001"
ZADD scores 100 "user:1000"
# データ挿入
redis.hmset('order:1', {
'year': 2022,
'month': 10,
'day': 26,
'customer_name': 'kaneko',
'product_name': 'orange A',
'unit_price': 1.2,
'qty': 10,
'created_at': datetime.now().isoformat(),
'updated_at': None
})
redis.hmset('order:2', {
'year': 2022,
'month': 10,
'day': 26,
'customer_name': 'miyamoto',
'product_name': 'Apple M',
'unit_price': 2.5,
'qty': 2,
'created_at': datetime.now().isoformat(),
'updated_at': None
})
redis.hmset('order:3', {
'year': 2022,
'month': 10,
'day': 27,
'customer_name': 'kaneko',
'product_name': 'orange B',
'unit_price': 1.2,
'qty': 8,
'created_at': datetime.now().isoformat(),
'updated_at': None
})
redis.hmset('order:4', {
'year': 2022,
'month': 10,
'day': 28,
'customer_name': 'miyamoto',
'product_name': 'Apple L',
'unit_price': 3.0,
'qty': 1,
'created_at': datetime.now().isoformat(),
'updated_at': None
})
問い合わせの実行と結果確認
【説明】SCAN操作による効率的な反復処理とHGETALLによる完全なハッシュデータの取得を行う.パターンマッチングを使用したキーの走査と条件フィルタリングの組み合わせにより,効率的なデータ検索を実現する.メモリ効率を考慮したイテレータパターンを採用する.
【補足:キー設計パターン】
<エンティティ名>:<ID>:<属性>
<インデックス名>:<値>
temp:<データ種別>:<ID>
# 全データの取得
for key in redis.scan_iter("order:*"):
print(redis.hgetall(key))
# 特定の日付のデータ取得
for key in redis.scan_iter("order:*"):
order = redis.hgetall(key)
if order['day'] == '26':
print(order)
# 特定の顧客のデータ取得
for key in redis.scan_iter("order:*"):
order = redis.hgetall(key)
if order['customer_name'] == 'kaneko':
print(order)
# 特定の単価以上のデータ取得
for key in redis.scan_iter("order:*"):
order = redis.hgetall(key)
if float(order['unit_price']) > 2:
print(order)
データ更新の実践的手法
【説明】HMSETによる複数フィールドの原子的な更新を実装する.更新時刻の自動管理とフィールド単位の部分更新による効率的なデータ管理を実現する.必要に応じてトランザクション制御と組み合わせることが可能である.
【補足:データ整合性を保つための実装パターン】
# トランザクションを使用した更新
pipe = redis.pipeline()
pipe.hset("users:1000", "department", "技術部")
pipe.srem("department:営業部", "1000")
pipe.sadd("department:技術部", "1000")
pipe.execute()
# 数量と更新時刻の更新
redis.hmset('order:1', {
'qty': 12,
'updated_at': datetime.now().isoformat()
})
効率的なデータ削除の方法
【説明】DELETEコマンドによるキー単位の削除を実装する.関連するインデックスの整合性を維持するためのトランザクション処理と組み合わせることが可能である.セカンダリインデックスの同期的な更新を確実に行う.
# 特定のデータの削除
redis.delete('order:2')
インデックスの活用
【説明】セット型を使用したセカンダリインデックスの実装を行う.SADDによるメンバー追加とSMEMBERSによる効率的な逆引き検索を実現する.キー設計パターンに基づく効率的なデータアクセスを可能とする.
# 顧客名によるインデックス作成
redis.sadd('customer:kaneko', 'order:1')
redis.sadd('customer:kaneko', 'order:3')
redis.sadd('customer:miyamoto', 'order:2')
redis.sadd('customer:miyamoto', 'order:4')
# インデックスを使用した検索
customer_orders = redis.smembers('customer:kaneko')
for order_id in customer_orders:
print(redis.hgetall(order_id))
# 日付によるインデックス作成
redis.sadd('day:26', 'order:1')
redis.sadd('day:26', 'order:2')
redis.sadd('day:27', 'order:3')
redis.sadd('day:28', 'order:4')
# 日付インデックスを使用した検索
day_orders = redis.smembers('day:26')
for order_id in day_orders:
print(redis.hgetall(order_id))
データのバックアップとリストア
【説明】組み込みのバックアップ機能とデータの永続化機能を活用する.SAVEコマンドによるスナップショット作成とBGSAVE(Background SAVE)による非同期バックアップを実装する.AOF(Append Only File)による操作ログの永続化を実現する.
【補足:Cache-Aside Pattern実装例】
def get_data(key):
cache = redis.get(key)
if not cache:
data = db.query(key) # メインDBから取得
redis.setex(key, 3600, data) # 1時間のTTLで保存
return cache
【補足:Redis Search活用例】
# インデックス作成
FT.CREATE users:index ON HASH PREFIX 1 users:
SCHEMA name TEXT age NUMERIC department TEXT
# 複合条件での検索
FT.SEARCH users:index "@department:技術部 @age:[20 30]"
RedisではSAVE
コマンドを使用してデータベースのスナップショットを作成できる.BGSAVE
を使用すると,バックグラウンドでスナップショットを作成する.
注意点:
MULTI
/EXEC
を使用して実現するこれらの操作は,アプリケーションのニーズに応じて適切に組み合わせることで,効率的なデータ管理が可能となる.