我已经实现了以下版本的ServiceStack .net核心Redis库:
ServiceStack.Redis.Core 5.9.2
我正在使用该库访问我创建的Redis缓存,以使用.NET Core3.1持久化我的AWS Serverless应用程序的值。我已经为ServiceStack Redis支付了商业许可。
我的应用程序在尝试创建Redis客户端时,会在没有警告的情况下定期捕获以下错误:
Exception: System.Exception: No master found in: redis-cluster-api-prd-lcs.in-xxxxxxxx:6379
at ServiceStack.Redis.RedisResolver.CreateRedisClient(RedisEndpoint config, Boolean master) in C:\BuildAgent\work\b2a0bfe2b1c9a118\src\ServiceStack.Redis\RedisResolver.cs:line 116
at ServiceStack.Redis.RedisResolver.CreateMasterClient(Int32 desiredIndex) in C:\BuildAgent\work\b2a0bfe2b1c9a118\src\ServiceStack.Redis\RedisResolver.cs:line 142
at ServiceStack.Redis.RedisManagerPool.GetClient() in C:\BuildAgent\work\b2a0bfe2b1c9a118\src\ServiceStack.Redis\RedisManagerPool.cs:line 174
at LCSApi.UtilityCommand.Cache.IsCacheValueExists(String cacheKey, RedisManagerPool pool) in D:\a\1\s\testapi\Utility.cs:line 167
at LCSApi.Functions.LcsConfigurationSweeper(ILambdaContext context) in D:\a\1\s\testapi\Function.cs:line 2028
Exception: System.Exception: No master found in: redis-cluster-api-prd-lcs.in在其他情况下,相同的代码也能正常工作。我的实现非常简单:
private readonly RedisManagerPool _redisClient;
_redisClient = new RedisManagerPool(Environment.GetEnvironmentVariable("CACHE_URL") + ":" +
Environment.GetEnvironmentVariable("CACHE_PORT"));
public static T GetCacheValue<T>(string cacheKey, RedisManagerPool pool)
{
T cacheValue;
try
{
//StackExchange.Redis.IDatabase cache = Functions._redisConnect.GetDatabase();
//string value = cache.StringGet(cacheKey);
//cacheValue = (T)Convert.ChangeType(value, typeof(T));
using (var client = pool.GetClient())
{
client.RetryCount = Convert.ToInt32(Environment.GetEnvironmentVariable("CACHE_RETRY_COUNT"));
client.RetryTimeout = Convert.ToInt32(Environment.GetEnvironmentVariable("CACHE_RETRY_TIMEOUT"));
cacheValue = client.Get<T>(cacheKey);
}
}
catch (Exception ex)
{
//Console.WriteLine($"[CACHE_EXCEPTION] {ex.ToString()}");
cacheValue = GetParameterSSMFallback<T>(cacheKey);
//Console.WriteLine($"[CACHE_EXCEPTION] Fallback SSM parameter --> {cacheValue}");
}
return cacheValue;
}这种情况发生得足够多了,我不得不编写一个“回退”例程来从AWS参数存储中获取该值。不是很理想。Redis的配置如下:

我在网上几乎找不到任何关于这个错误的信息。我曾尝试注册ServiceStack论坛,但没有成功,由于某些原因,即使我有商业许可证,它也不让我注册。有人能帮上忙吗?
发布于 2020-09-24 21:11:25
该错误是由于网络实例未连接到redis ROLE命令标识的主实例。这可能发生在during an ElastiCache failover,最终主实例将以原始DNS名称返回:
Redis的Amazon将通过获取新的服务资源来修复节点,然后将节点的现有ElastiCache名称重定向到新的服务资源。因此,Redis节点的DNS名称保持不变,但Redis节点的IP地址可以随时间变化。
ServiceStack.Redis会尝试使用所有指定的主连接(通常只有1个)连接到主实例。如果无法连接到主实例,则必须放弃,因为客户端希望在读/写主实例上执行操作。
如果预计主实例将以相同的DNS名称返回,我们可以使用自定义IRedisResolver在指定的时间段内连续重试连接主实例的同一连接,例如:
public class ElasticCacheRedisResolver : RedisResolver
{
public override RedisClient CreateRedisClient(RedisEndpoint config, bool master)
{
if (master)
{
//ElastiCache Redis will failover & retain same DNS for master
var firstAttempt = DateTime.UtcNow;
Exception firstEx = null;
var retryTimeSpan = TimeSpan.FromMilliseconds(config.RetryTimeout);
var i = 0;
while (DateTime.UtcNow - firstAttempt < retryTimeSpan) {
try
{
var client = base.CreateRedisClient(config, master:true);
return client;
}
catch (Exception ex)
{
firstEx ??= ex;
ExecUtils.SleepBackOffMultiplier(++i);
}
}
throw new TimeoutException(
$"Could not resolve master within {config.RetryTimeout}ms RetryTimeout", firstEx);
}
return base.CreateRedisClient(config, master:false);
}
}使用您的Redis客户端管理器进行配置,例如:
private static readonly RedisManagerPool redisManager;
redisManager = new RedisManagerPool(...) {
RedisResolver = new ElasticCacheRedisResolver()
};注意:在这里你应该只使用一个共享的Redis Client Managers实例,比如RedisManagerPool,这样它们就可以共享同一个连接池。如果包含redisManager的类不是单例,则应将其分配给静态字段,以确保使用相同的单例实例来检索客户端。
https://stackoverflow.com/questions/64045448
复制相似问题