首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Redis python -如何根据Python中的特定模式删除所有键,而无需python迭代

Redis python -如何根据Python中的特定模式删除所有键,而无需python迭代
EN

Stack Overflow用户
提问于 2014-02-23 22:01:55
回答 9查看 114.5K关注 0票数 56

我正在编写django管理命令,以处理部分redis缓存。基本上,我需要选择所有的键,以确认一个特定的模式(例如:“前缀:*”)并删除它们。

我知道我可以用cli来做:

代码语言:javascript
运行
复制
redis-cli KEYS "prefix:*" | xargs redis-cli DEL

但我需要在应用程序中完成这个任务。所以我需要使用python绑定(我使用py-redis)。我试过将一个列表输入删除,但失败了:

代码语言:javascript
运行
复制
from common.redis_client import get_redis_client
cache = get_redis_client()
x = cache.keys('prefix:*') 

x == ['prefix:key1','prefix:key2'] # True

而现在

代码语言:javascript
运行
复制
cache.delete(x) 

返回0。没有任何东西被删除

我知道我可以在x上迭代:

代码语言:javascript
运行
复制
for key in x:
   cache.delete(key)

但这将失去红色惊人的速度和滥用它的能力。有没有没有迭代和/或cli的具有py-redis的pythonic解?

谢谢!

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2014-02-23 22:17:48

我认为

代码语言:javascript
运行
复制
 for key in x: cache.delete(key)

很好也很简洁。delete一次只想要一个键,所以你必须循环。

否则,此先前的问题和答案将指向基于lua的解决方案。

票数 25
EN

Stack Overflow用户

发布于 2016-05-10 09:59:28

使用扫描迭代器:https://pypi.python.org/pypi/redis

代码语言:javascript
运行
复制
for key in r.scan_iter("prefix:*"):
    r.delete(key)
票数 55
EN

Stack Overflow用户

发布于 2017-07-17 20:55:51

下面是一个使用皮瑞迪斯的完整示例

代码语言:javascript
运行
复制
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

干杯!

更新:

在编写答案之后,我开始使用redis的管道特性在一个请求中发送所有命令,并避免网络延迟:

代码语言:javascript
运行
复制
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,则可以使用自己的逻辑控制块大小并迭代游标。这似乎也要快得多,特别是在处理许多密钥时。如果在其中添加管道,您将获得一些性能提升,10%-25%取决于块大小,而代价是内存使用,因为在生成所有内容之前,您不会将执行命令发送到Redis。所以我坚持做扫描:

代码语言:javascript
运行
复制
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块:

代码语言:javascript
运行
复制
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):

代码语言:javascript
运行
复制
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
票数 34
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21975228

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档