Redis: Improving Redis extensions use of keys (#7532) (#5958 re-applied)

This commit is contained in:
Carl Woodhouse
2017-01-24 15:25:08 +01:00
committed by Benedek Farkas
parent 06a2e0d6b1
commit 8615422e27
4 changed files with 15 additions and 56 deletions

View File

@@ -58,7 +58,7 @@ namespace Orchard.Redis.Caching {
} }
public void Clear() { public void Clear() {
Database.KeyDeleteWithPrefix(GetLocalizedKey("*")); _connectionMultiplexer.KeyDeleteWithPrefix(GetLocalizedKey("*"));
} }
private string GetLocalizedKey(string key) { private string GetLocalizedKey(string key) {

View File

@@ -1,41 +0,0 @@
using System;
using StackExchange.Redis;
namespace Orchard.Redis.Extensions {
public static class RedisDatabaseExtensions {
public static void KeyDeleteWithPrefix(this IDatabase database, string prefix) {
if (database == null) {
throw new ArgumentException("Database cannot be null", "database");
}
if (string.IsNullOrWhiteSpace(prefix)) {
throw new ArgumentException("Prefix cannot be empty", "database");
}
database.ScriptEvaluate(@"
local keys = redis.call('keys', ARGV[1])
for i=1,#keys,5000 do
redis.call('del', unpack(keys, i, math.min(i+4999, #keys)))
end", values: new RedisValue[] { prefix });
}
public static int KeyCount(this IDatabase database, string prefix) {
if (database == null) {
throw new ArgumentException("Database cannot be null", "database");
}
if (string.IsNullOrWhiteSpace(prefix)) {
throw new ArgumentException("Prefix cannot be empty", "database");
}
var retVal = database.ScriptEvaluate("return table.getn(redis.call('keys', ARGV[1]))", values: new RedisValue[] { prefix });
if (retVal.IsNull) {
return 0;
}
return (int)retVal;
}
}
}

View File

@@ -110,7 +110,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Caching\RedisCacheStorageProvider.cs" /> <Compile Include="Caching\RedisCacheStorageProvider.cs" />
<Compile Include="Extensions\RedisDatabaseExtensions.cs" /> <Compile Include="Extensions\RedisConnectionExtensions.cs" />
<Compile Include="Configuration\IRedisConnectionProvider.cs" /> <Compile Include="Configuration\IRedisConnectionProvider.cs" />
<Compile Include="Configuration\RedisConnectionProvider.cs" /> <Compile Include="Configuration\RedisConnectionProvider.cs" />
<Compile Include="MessageBus\RedisMessageBusBroker.cs" /> <Compile Include="MessageBus\RedisMessageBusBroker.cs" />

View File

@@ -54,7 +54,7 @@ namespace Orchard.Redis.OutputCache {
} }
public void Set(string key, CacheItem cacheItem) { public void Set(string key, CacheItem cacheItem) {
if(cacheItem == null) { if (cacheItem == null) {
throw new ArgumentNullException("cacheItem"); throw new ArgumentNullException("cacheItem");
} }
@@ -74,7 +74,7 @@ namespace Orchard.Redis.OutputCache {
} }
public void RemoveAll() { public void RemoveAll() {
Database.KeyDeleteWithPrefix(GetLocalizedKey("*")); Database.KeyDelete(GetPrefixedKeys().Select(key => (RedisKey)key).ToArray());
} }
public CacheItem GetCacheItem(string key) { public CacheItem GetCacheItem(string key) {
@@ -85,11 +85,11 @@ namespace Orchard.Redis.OutputCache {
} }
using (var compressedStream = new MemoryStream(value)) { using (var compressedStream = new MemoryStream(value)) {
if(compressedStream.Length == 0) { if (compressedStream.Length == 0) {
return null; return null;
} }
using(var decompressedStream = Decompress(compressedStream)) { using (var decompressedStream = Decompress(compressedStream)) {
return Deserialize(decompressedStream); return Deserialize(decompressedStream);
} }
} }
@@ -106,7 +106,7 @@ namespace Orchard.Redis.OutputCache {
} }
public int GetCacheItemsCount() { public int GetCacheItemsCount() {
return Database.KeyCount(GetLocalizedKey("*")); return GetPrefixedKeys().Count();
} }
/// <summary> /// <summary>
@@ -123,19 +123,19 @@ namespace Orchard.Redis.OutputCache {
/// </summary> /// </summary>
/// <returns>The keys for the current tenant.</returns> /// <returns>The keys for the current tenant.</returns>
private IEnumerable<string> GetAllKeys() { private IEnumerable<string> GetAllKeys() {
var prefix = GetLocalizedKey("");
return GetPrefixedKeys().Select(x => x.Substring(prefix.Length));
}
private IEnumerable<string> GetPrefixedKeys() {
// prevent the same request from computing the list twice (count + list) // prevent the same request from computing the list twice (count + list)
if (_keysCache == null) { if (_keysCache == null) {
_keysCache = new HashSet<string>(); _keysCache = new HashSet<string>();
var prefix = GetLocalizedKey(""); var keys = _connectionMultiplexer.GetKeys(GetLocalizedKey("*"));
foreach (var key in keys) {
foreach (var endPoint in _connectionMultiplexer.GetEndPoints()) { _keysCache.Add(key);
var server = _connectionMultiplexer.GetServer(endPoint);
foreach (var key in server.Keys(pattern: GetLocalizedKey("*"))) {
_keysCache.Add(key.ToString().Substring(prefix.Length));
}
} }
} }
return _keysCache; return _keysCache;
} }