Redisで大きなハッシュを安全に削除する方法
Redisで大きなオブジェクトの削除が遅くなる理由について、まずは概要をご覧ください。大きなキーに対して直接 DEL コマンドを実行すると、Redisはシングルスレッドで動作しているため、削除処理が完了するまでサーバー全体がブロックされ、他のすべてのクライアントに影響を与えてしまいます。
そこで、大きなハッシュをサーバーをブロックせずに削除するには、以下の2段階のアプローチを使用します。
キーの名前を変更する:ハッシュのキーを一意な名前空間付きの新しいキーにリネームします。これにより、他のRedisクライアントからは即座に「削除された」ように見えます。
フィールドを少しずつ削除する:ハッシュ内のフィールドを小さなバッチ(例:100件ずつ)でインクリメンタルに削除し、ハッシュが空になるまで繰り返します。削除コマンドのサイズを制限することで、サーバーが長時間ブロックされるのを防ぎます。
注意点
以下のコード例では、Redis接続の失敗は考慮していません。いずれかのRedisコマンドが失敗して例外が発生した場合は、手動でクリーンアップを行う必要があります。本番環境で使用する場合は、エラーハンドリングとリトライ処理を追加することをおすすめします。
擬似コード
# キーをリネームする
newkey = "gc:hashes:" + redis.INCR("gc:index")
redis.RENAME("my.hash.key", newkey)
# ハッシュのフィールドを100件ずつのバッチで削除する
cursor = 0
loop
cursor, hash_keys = redis.HSCAN(newkey, cursor, "COUNT", 100)
if hash_keys count > 0
redis.HDEL(newkey, hash_keys)
end
if cursor == 0
break
end
end
Rubyでの実装
$redis = Redis.new
def delete_hash(key)
# キーをリネームする
newkey = "gc:hashes:#{$redis.incr("gc:index")}"
$redis.rename(key, newkey)
# フィールドを100件ずつのバッチで削除する
cursor = "0"
loop do
cursor, fields = $redis.hscan(newkey, cursor, count: 100)
hkeys = fields.map { |pair| pair[0] }
$redis.hdel(newkey, hkeys) if hkeys.size > 0
break if cursor == "0"
end
end
# 使用例:
#
# delete_hash("my.large.hash")
バックグラウンドジョブでの実行
この削除処理は時間がかかる可能性があるため、バックグラウンドジョブとして実行するのが理想的です。Rubyでは、以下のようなジョブフレームワークを使った実装例があります。
- Resque
- Sidekiq
バックグラウンドジョブで実行することで、Webリクエストの応答時間に影響を与えることなく、大きなハッシュを安全に削除できます。
← 「Redisで大きなオブジェクトを削除する」に戻る
-
Redisのハッシュ徹底解説!基本コマンドから実践的な活用例まで
Redisのハッシュ(Hash)は、1つのキーの下に複数の「フィールドと値」のペアを関連付けて格納できるデータ構造です。フィールドも値も文字列として扱われ、データ構造全体だけでなく、構造内の個々のフィールド単位でも柔軟に変更できるのが大きな特徴です。この特性により、アプリケーション内のオブジェクトを保存するバックエンドストアとして、非常に高速かつ理想的な選択肢となります。CLIで学ぶハッシュの基本操作まずは、2つのフィールドを持つハッシュを作成してみましょう。127.0.0.1:6379> HMSET my_hash key1 foo key2 bar OKハッシュに関連付けられたすべて
-
Fastly ComputeでUpstash Redisを活用する方法
この記事では古いバージョンのFastly CLIを使用しています。最新の手順については、こちらの記事をご確認ください。 この記事では、Fastly Compute@Edge上で動作するシンプルなアプリケーションを作成します。このアプリケーションはUpstash Redisにアクセスし、ページビュー数を記録します。 モチベーション エッジコンピューティングは、近年最も注目されているトレンドのひとつです。CloudflareやFastlyといったCDNサービスは、ユーザーが自社のエッジインフラストラクチャ上でアプリケーションを実行できるようにしました。これにより、開発者はグローバルに分散した高