py-redisを使用した完全な動作例を次に示します。
from redis import StrictRedis
cache = StrictRedis()
def clear_ns(ns):
"""
Clears a namespace
:param ns: str, namespace i.e your:prefix
:return: int, cleared keys
"""
count = 0
ns_keys = ns + '*'
for key in cache.scan_iter(ns_keys):
cache.delete(key)
count += 1
return count
scan_iter
また、すべてのキーをメモリに取得し、一括削除のためにすべてのキーを渡すこともできますがdelete
、名前空間が大きい場合は大量のメモリが必要になる場合があります。delete
そのため、キーごとに a を実行するのがおそらく最善です。
乾杯!
アップデート:
回答を書いて以来、redis のパイプライン機能を使用して、すべてのコマンドを 1 つの要求で送信し、ネットワークの遅延を回避し始めました。
from redis import StrictRedis
cache = StrictRedis()
def clear_cache_ns(ns):
"""
Clears a namespace in redis cache.
This may be very time consuming.
:param ns: str, namespace i.e your:prefix*
:return: int, num cleared keys
"""
count = 0
pipe = cache.pipeline()
for key in cache.scan_iter(ns):
pipe.delete(key)
count += 1
pipe.execute()
return count
UPDATE2 (最高のパフォーマンス):
scan
の代わりにを使用するとscan_iter
、チャンク サイズを制御し、独自のロジックを使用してカーソルを反復処理できます。これは、特に多くのキーを処理する場合に、はるかに高速であるようにも見えます。これにパイプラインを追加すると、すべてが生成されるまで実行コマンドを Redis に送信しないため、メモリ使用量を犠牲にして、チャンク サイズに応じて 10 ~ 25% のパフォーマンス向上が得られます。だから私はスキャンに固執しました:
from redis import StrictRedis
cache = StrictRedis()
CHUNK_SIZE = 5000
def clear_ns(ns):
"""
Clears a namespace
:param ns: str, namespace i.e your:prefix
:return: int, cleared keys
"""
cursor = '0'
ns_keys = ns + '*'
while cursor != 0:
cursor, keys = cache.scan(cursor=cursor, match=ns_keys, count=CHUNK_SIZE)
if keys:
cache.delete(*keys)
return True
いくつかのベンチマークを次に示します。
ビジー状態の Redis クラスターを使用した 5k チャンク:
Done removing using scan in 4.49929285049
Done removing using scan_iter in 98.4856731892
Done removing using scan_iter & pipe in 66.8833789825
Done removing using scan & pipe in 3.20298910141
5k チャンクと小さなアイドル状態の dev redis (localhost):
Done removing using scan in 1.26654982567
Done removing using scan_iter in 13.5976779461
Done removing using scan_iter & pipe in 4.66061878204
Done removing using scan & pipe in 1.13942599297