我在生产中使用servicestack的redis客户端时遇到错误。
对于redisclient.containskey,错误为“unknown reply on integer response:43ok”,对于redisclient.get,错误为“zero length response”。
应用程序使用redis sentinel和poolredisclientmanager。我有 Package 类来初始化redis示例和redis操作:
public class RedisFactory : IRedisFactory
{
private RedisSentinel redisSentinel;
private IRedisClientsManager clientsManager;
public void Init()
{
RedisConfig.DefaultRetryTimeout = RETRY_TIMEOUT; //5000ms
RedisClientManagerConfig config = new RedisClientManagerConfig()
{
MaxReadPoolSize = MAX_POOL_SIZE, //40
MaxWritePoolSize = MAX_POOL_SIZE, //40
DefaultDb = DEFAUTL_DB
};
redisSentinel = new RedisSentinel(sentinelHosts, masterName: masterName)
{
RedisManagerFactory = (master, slaves) => new PooledRedisClientManager(master.ToList(), slaves.ToList(), config)
{
NamespacePrefix = NAMESPACE_PREFIX
},
OnFailover = manager => _log.Info($"Fail over at {DateTime.Now}"),
OnWorkerError = ex => _log.Error($"Sentinel worker error \n {ex}"),
OnSentinelMessageReceived = (channel, msg) => _log.Info($"Received '{channel}' on channel '{msg}' from Sentinel")
};
clientsManager = redisSentinel.Start();
}
public bool KeyExisted(string key)
{
Func<string, bool> keyExisted = delegate (string k)
{
using (var slave = clientsManager.GetReadonlyClient())
{
var existed = slave.ContainsKey(k);
return existed;
}
};
return Execute(nameof(keyExisted), key, keyExisted);
}
public T Get<T>(string key)
{
Func<string, T> get = delegate (string k)
{
using (var slave = clientsManager.GetReadonlyClient())
{
var value = slave.Get<T>(k);
return value;
}
};
return Execute(nameof(get), key, get);
}
private T Execute<T>(string operation, string key, Func<string, T> func)
{
int retry = 0;
while (true)
{
try
{
return func(key);
}
catch (Exception ex)
{
_log.Error($"Redis operation: {operation} error \n {ex}");
if (ex is RedisException)
{
if (retry >= 3)
{
throw;
}
retry++;
}
else
{
throw;
}
}
}
}
}
Package 器在apphost中注册为单例示例
public class AppHost : AppHostBase { public override void Configure(Container container){
var redisFactory = new RedisFactory
{
MaxPoolSize = AppSettings.Get("MaxPoolSize", 40),
MaxRetryAttempts = AppSettings.Get("MaxRetryAttempts", 3),
RetryTimeout = AppSettings.Get("RetryTimeout", 5000),
NameSpacePrefix = AppSettings.GetString("NameSpacePrefix"),
DefaultDB = 13
}; redisFactory.Init(); container.Register<IRedisFactory>(redisFactory);}}
redis工厂使用
public class MyService
{
private IRedisFactory cacheClient = HostContext.TryResolve<IRedisFactory>();
public object SomeMethod(string key) => cacheClient.Get<object>(key);
}
我有一个redisfactory::execute中的重试函数。我注意到第一次尝试将抛出如下异常,但第二次尝试将成功。
ServiceStack.Redis.RedisResponseException: Unknown reply on integer response: 43OK
at ServiceStack.Redis.RedisNativeClient.ReadLong()
at ServiceStack.Redis.RedisNativeClient.SendReceive[T](Byte[][] cmdWithBinaryArgs, Func`1 fn, Action`1 completePipelineFn, Boolean sendWithoutRead)
at ServiceStack.Redis.RedisNativeClient.SendExpectLong(Byte[][] cmdWithBinaryArgs)
at ServiceStack.Redis.RedisClient.ContainsKey(String key)
at RedisLibrary.RedisFactory.<KeyExisted>b__30_0(String k)
ServiceStack.Redis.RedisResponseException: Zero length response
at ServiceStack.Redis.RedisNativeClient.ParseSingleLine(String r)
at ServiceStack.Redis.RedisNativeClient.SendReceive[T](Byte[][] cmdWithBinaryArgs, Func`1 fn, Action`1 completePipelineFn, Boolean sendWithoutRead)
at ServiceStack.Redis.RedisNativeClient.SendExpectData(Byte[][] cmdWithBinaryArgs)
at ServiceStack.Redis.RedisClient.<>c__DisplayClass131_0`1.<Get>b__0(RedisClient r)
at ServiceStack.Redis.RedisClient.Exec[T](Func`2 action)
at RedisLibrary.RedisFactory.<Get>b__31_0[T](String k)
这只发生在containskey和get操作中。添加、删除或替换仍在正常工作。
需要注意的一点是,自从我们更改redis服务器配置后,在生产中发现了以下错误:
//redis服务器配置更改
Fail over – timeout redis -cluster 5000 ->15000
Tcp-keepalive 0 ->300
Repl -blacklog-size 10mb -> 50mb
我尝试在测试环境中用与生产环境中相同的redis配置重现这个问题,但失败了。我还一直在寻找其他类似的问题,例如在servicestack中共享相同的redis客户端。redis client unknown reply on integer response:430k,但没有任何帮助。
有人能帮我指出我的实现或redis配置有什么问题吗?谢谢你的帮助。
暂无答案!
目前还没有任何答案,快来回答吧!