从StackExchange.Redis缓存中删除所有/一个项目

60

我正在使用StackExchange.Redis客户端与Azure Redis缓存服务。这是我的类,

public class RedisCacheService : ICacheService
{
    private readonly ISettings _settings;
    private readonly IDatabase _cache;

    public RedisCacheService(ISettings settings)
    {
        _settings = settings;
        var connectionMultiplexer = ConnectionMultiplexer.Connect(settings.RedisConnection);
        _cache = connectionMultiplexer.GetDatabase();
    }

    public bool Exists(string key)
    {
        return _cache.KeyExists(key);
    }

    public void Save(string key, string value)
    {
        var ts = TimeSpan.FromMinutes(_settings.CacheTimeout);
        _cache.StringSet(key, value, ts);
    }

    public string Get(string key)
    {
        return _cache.StringGet(key);
    }

    public void Remove(string key)
    {
        // How to remove one
    }

    public void Clear()
    {
        // How to remove all
    }
}

更新:在Marc的帮助下,这是我的最终类。

public class RedisCacheService : ICacheService
{
    private readonly ISettings _settings;
    private readonly IDatabase _cache;
    private static ConnectionMultiplexer _connectionMultiplexer;

    static RedisCacheService()
    {
        var connection = ConfigurationManager.AppSettings["RedisConnection"];
        _connectionMultiplexer = ConnectionMultiplexer.Connect(connection);
    }

    public RedisCacheService(ISettings settings)
    {
        _settings = settings;
        _cache = _connectionMultiplexer.GetDatabase();
    }

    public bool Exists(string key)
    {
        return _cache.KeyExists(key);
    }

    public void Save(string key, string value)
    {
        var ts = TimeSpan.FromMinutes(_settings.CacheTimeout);
        _cache.StringSet(key, value, ts);
    }

    public string Get(string key)
    {
        return _cache.StringGet(key);
    }

    public void Remove(string key)
    {
        _cache.KeyDelete(key);
    }

    public void Clear()
    {
        var endpoints = _connectionMultiplexer.GetEndPoints(true);
        foreach (var endpoint in endpoints)
        {
            var server = _connectionMultiplexer.GetServer(endpoint);
            server.FlushAllDatabases();    
        }
    }
}

现在我不知道如何从 Redis 缓存中删除所有项目或单个项目。


8
附带说明:我强烈建议在Redis前面添加内存缓存;Redis很快,但是不需要进行的Redis请求会更快。 - Marc Gravell
1
@MarcGravell,我同意,这就是为什么我也使用了.Net内存缓存。但它并不是分布式的,这意味着我需要多个服务器的支持。 - Imran Qadir Baksh - Baloch
@MarcGravell 我之所以使用Redis是因为我有一个具有许多应用服务器的可扩展环境。在这种情况下,内存缓存是行不通的,对吗? - Issa Fram
1
@IssaFram 当然可以 - 只要您有某种发布缓存失效的策略。幸运的是,redis内置了pub/sub功能,并且如果您真的想要,可以启用keyspace通知。我们使用完全相同的设置(通过选择在我们希望立即失效的关键字上进行选择性发布,而不是通过自动化keyspace通知)来处理多服务器集群上的内存+redis缓存。 - Marc Gravell
5个回答

77
删除单个项目的方法:

要删除单个项目:

_cache.KeyDelete(key);

要删除所有内容,需要使用FLUSHDBFLUSHALL Redis命令;两者均可在StackExchange.Redis中使用;但是,由于这里讨论的原因,它们不在IDatabase API上(因为:它们会影响服务器,而不是逻辑数据库)。

根据该页面上的“那么我如何使用它们?”:

server.FlushDatabase(); // to wipe a single database, 0 by default
server.FlushAllDatabases(); // to wipe all databases

(很可能在使用多路复用器的GetEndpoints()之后)


4
谢谢。我该如何获取服务器? - Imran Qadir Baksh - Baloch
1
从多路复用器中获取@user960567;multiplexer.GetServer(...);最简单的方法是从multiplexer.GetEndpoints(true)请求一个端点。显然,如果您只与一个服务器通信,这一切都会变得更加容易。所有这些都在链接文章的末尾有解释。 - Marc Gravell
但是我只有来自 Azure 的连接字符串,xx.redis.cache.windows.net,ssl=true,password=...。那么我该如何获取服务器呢? - Imran Qadir Baksh - Baloch
我的RedisCacheService是按请求(asp.net)的方式运行的。每个请求实例化ConnectionMultiplexer和IDatabase是否合适? - Imran Qadir Baksh - Baloch
1
@user960567,实际上我非常确定他们确实这样做了,但是:我怀疑对于外部调用者来说可能不可用;因此,如果您只知道一个地址,那么很有可能它是主节点,并且GetEndpoints将返回恰好一个项目。 - Marc Gravell
显示剩余6条评论

28

我无法在Azure Redis Cache中清除数据库,提示错误:

未启用管理员模式时无法使用此操作:FLUSHDB

请通过迭代所有键来删除:

var endpoints = connectionMultiplexer.GetEndPoints();
var server = connectionMultiplexer.GetServer(endpoints.First());
//FlushDatabase didn't work for me: got error admin mode not enabled error
//server.FlushDatabase();
var keys = server.Keys();
foreach (var key in keys)
{
  Console.WriteLine("Removing Key {0} from cache", key.ToString());
  _cache.KeyDelete(key);
}

18
请确保在配置字符串(或“ConfigurationOptions”)中设置“allowAdmin = true”。https://github.com/StackExchange/StackExchange.Redis/blob/master/Docs/Configuration.md#basic-configuration-strings - Sean Kearney
1
@SeanKearney - 这个链接已经失效了。这是更新后的链接:https://stackexchange.github.io/StackExchange.Redis/Configuration#configuration-options - Karthik

14

@Rasi 和 @Marc Gravell 的回答都包含所需的代码片段。 基于上述内容,下面是一个假设只有 1 个服务器的可工作的代码片段:

您需要使用 allowAdmin=true 连接到 Redis,一种获得这种选项的方法是将 AllowAdmin 分配给已解析的字符串:

var options = ConfigurationOptions.Parse("server:6379");
options.AllowAdmin = true;
var redis = ConnectionMultiplexer.Connect(options);

然后执行清空所有数据库的命令:


var endpoints = redis.GetEndPoints();
var server = redis.GetServer(endpoints[0]);
server.FlushAllDatabases();

上述方法适用于任何Redis部署,不仅限于Azure。


1
您也可以删除哈希值,例如,如果您想从任何已缓存列表中清除特定值。例如,我们有一个员工列表,并在其中缓存了不同的部门。
public static void DeleteHash(string key, string cacheSubKey)
        {
            if (string.IsNullOrEmpty(key))
                throw new ArgumentNullException("key");

            Cache.HashDelete(key, cacheSubKey);
        }

因此,您可以传递键名和缓存子键。


0

要从分布式缓存中的列表中删除项目,请使用由分布式缓存库支持的ListRemoveAsync()函数,并可通过IDistributedCache接口访问。

 public async Task RemoveListByIndexAsync(string key, string cacheValue)
 {
   RedisValue redisValue = cacheValue // value of item in the list to be removed;
   await _cache.ListRemoveAsync(key, redisValue);
 }
  • key - 缓存键 redisValue
  • item - 要删除的列表项。

注意 - 确保要删除的 Redis 值应该与缓存中现有的列表项完全相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接