Redis extensions use of keys #5958

This commit is contained in:
Carl Woodhouse
2015-10-20 12:35:34 +01:00
parent 4574a9fb0b
commit eecb61a132
5 changed files with 55 additions and 56 deletions

View File

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

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using StackExchange.Redis;
namespace Orchard.Redis.Extensions {
public static class RedisConnectionExtensions {
public static void KeyDeleteWithPrefix(this IConnectionMultiplexer connection, string prefix) {
var keys = GetKeys(connection, prefix);
var database = connection.GetDatabase();
database.KeyDelete(keys.Select(key => (RedisKey)key).ToArray());
}
public static int KeyCount(this IConnectionMultiplexer connection, string prefix) {
return GetKeys(connection, prefix).Count();
}
// CYCLES EACH ENDPOINT FOR A CONNECTION SO KEYS ARE FETECHED IN A REDIS CLUSTER CONFIGURATION
// STACKEXCHANGECLIENT .KEYS WILL PERFORM SCAN ON REDIS SERVERS THAT SUPPORT IT
public static IEnumerable<string> GetKeys(this IConnectionMultiplexer connection, string prefix) {
if (connection == null) {
throw new ArgumentException("Connection cannot be null", "connection");
}
if (string.IsNullOrWhiteSpace(prefix)) {
throw new ArgumentException("Prefix cannot be empty", "database");
}
var keys = new List<string>();
var databaseId = connection.GetDatabase().Database;
foreach (var endPoint in connection.GetEndPoints()) {
var server = connection.GetServer(endPoint);
keys.AddRange(server.Keys(pattern: prefix, database: databaseId).Select(x => x.ToString()));
}
return keys.Distinct();
}
}
}

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

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

View File

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