Redis入門

  1. Redisの基本的なデータ構造と活用例
  2. SQLライクな操作の実現方法
  3. 効率的なキー設計パターン
  4. 実用的なキャッシュ戦略
    # 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
  5. データ整合性を保つための重要な実装パターン
    # トランザクション(不可分な処理のまとまり)を使用した更新
    pipe = redis.pipeline()
    pipe.hset("users:1000", "department", "技術部")  # ユーザーの部署を更新
    pipe.srem("department:営業部", "1000")  # 旧所属からの削除
    pipe.sadd("department:技術部", "1000")  # 新所属への追加
    pipe.execute()  # トランザクションの実行
  6. メモリ管理のベストプラクティス
  7. 高度な検索機能(Redis Search)の活用
    # インデックス作成
    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]"
  8. スケーラビリティ対策

これらの実装パターンは,アプリケーションの要件に応じて適切に組み合わせることで,高速で信頼性の高いシステムを構築することが可能である.

Redis演習

  1. 学習目標と内容
    既存データベースのRedisでの操作方法を習得し,データ構造とインデックスの実装技術を理解する.

  2. 環境設定と準備作業
    Redisのインストール手順(Ubuntu環境)では,ターミナルで以下のコマンドを実行する.

    sudo apt -y install redis-server
  3. Redisコマンドラインの起動と基本操作
    起動手順:redis-cliコマンドを実行することでRedisのコマンドラインインターフェースを起動する.

    ヘルプ機能の利用方法:helpコマンドを実行すると,利用可能な全てのコマンドと機能の一覧が表示される.

    終了手順:exitコマンドを実行することで,セッションを安全に終了することができる.

  4. データの挿入手順

    ここではorder_records(注文記録)データを登録する.Hash(ハッシュ型)を使用して構造化データを格納する.

    【説明】HashデータモデルによるレコードのRDB(リレーショナルデータベース)相当の永続化を行う.HMSETを使用してフィールドと値のペアを一括設定する.ISO8601形式のタイムスタンプを使用した時刻管理を実施する.データの一貫性はアプリケーション層で担保する.

    【補足:基本的なデータ構造】

    # データ挿入
    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
    })
  5. 問い合わせの実行と結果確認

    【説明】SCAN操作による効率的な反復処理とHGETALLによる完全なハッシュデータの取得を行う.パターンマッチングを使用したキーの走査と条件フィルタリングの組み合わせにより,効率的なデータ検索を実現する.メモリ効率を考慮したイテレータパターンを採用する.

    【補足:キー設計パターン】

    # 全データの取得
    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)
  6. データ更新の実践的手法

    【説明】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()
    })
  7. 効率的なデータ削除の方法

    【説明】DELETEコマンドによるキー単位の削除を実装する.関連するインデックスの整合性を維持するためのトランザクション処理と組み合わせることが可能である.セカンダリインデックスの同期的な更新を確実に行う.

    # 特定のデータの削除
    redis.delete('order:2')
  8. インデックスの活用

    【説明】セット型を使用したセカンダリインデックスの実装を行う.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))
  9. データのバックアップとリストア

    【説明】組み込みのバックアップ機能とデータの永続化機能を活用する.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を使用すると,バックグラウンドでスナップショットを作成する.

    注意点:

これらの操作は,アプリケーションのニーズに応じて適切に組み合わせることで,効率的なデータ管理が可能となる.