servicestack.redis对整数响应和零长度响应的未知响应

wmtdaxz3  于 2021-06-09  发布在  Redis
关注(0)|答案(0)|浏览(710)

我在生产中使用servicestack的redis客户端时遇到错误。
对于redisclient.containskey,错误为“unknown reply on integer response:43ok”,对于redisclient.get,错误为“zero length response”。
应用程序使用redis sentinel和poolredisclientmanager。我有 Package 类来初始化redis示例和redis操作:

  1. public class RedisFactory : IRedisFactory
  2. {
  3. private RedisSentinel redisSentinel;
  4. private IRedisClientsManager clientsManager;
  5. public void Init()
  6. {
  7. RedisConfig.DefaultRetryTimeout = RETRY_TIMEOUT; //5000ms
  8. RedisClientManagerConfig config = new RedisClientManagerConfig()
  9. {
  10. MaxReadPoolSize = MAX_POOL_SIZE, //40
  11. MaxWritePoolSize = MAX_POOL_SIZE, //40
  12. DefaultDb = DEFAUTL_DB
  13. };
  14. redisSentinel = new RedisSentinel(sentinelHosts, masterName: masterName)
  15. {
  16. RedisManagerFactory = (master, slaves) => new PooledRedisClientManager(master.ToList(), slaves.ToList(), config)
  17. {
  18. NamespacePrefix = NAMESPACE_PREFIX
  19. },
  20. OnFailover = manager => _log.Info($"Fail over at {DateTime.Now}"),
  21. OnWorkerError = ex => _log.Error($"Sentinel worker error \n {ex}"),
  22. OnSentinelMessageReceived = (channel, msg) => _log.Info($"Received '{channel}' on channel '{msg}' from Sentinel")
  23. };
  24. clientsManager = redisSentinel.Start();
  25. }
  26. public bool KeyExisted(string key)
  27. {
  28. Func<string, bool> keyExisted = delegate (string k)
  29. {
  30. using (var slave = clientsManager.GetReadonlyClient())
  31. {
  32. var existed = slave.ContainsKey(k);
  33. return existed;
  34. }
  35. };
  36. return Execute(nameof(keyExisted), key, keyExisted);
  37. }
  38. public T Get<T>(string key)
  39. {
  40. Func<string, T> get = delegate (string k)
  41. {
  42. using (var slave = clientsManager.GetReadonlyClient())
  43. {
  44. var value = slave.Get<T>(k);
  45. return value;
  46. }
  47. };
  48. return Execute(nameof(get), key, get);
  49. }
  50. private T Execute<T>(string operation, string key, Func<string, T> func)
  51. {
  52. int retry = 0;
  53. while (true)
  54. {
  55. try
  56. {
  57. return func(key);
  58. }
  59. catch (Exception ex)
  60. {
  61. _log.Error($"Redis operation: {operation} error \n {ex}");
  62. if (ex is RedisException)
  63. {
  64. if (retry >= 3)
  65. {
  66. throw;
  67. }
  68. retry++;
  69. }
  70. else
  71. {
  72. throw;
  73. }
  74. }
  75. }
  76. }
  77. }

Package 器在apphost中注册为单例示例

  1. public class AppHost : AppHostBase { public override void Configure(Container container){
  2. var redisFactory = new RedisFactory
  3. {
  4. MaxPoolSize = AppSettings.Get("MaxPoolSize", 40),
  5. MaxRetryAttempts = AppSettings.Get("MaxRetryAttempts", 3),
  6. RetryTimeout = AppSettings.Get("RetryTimeout", 5000),
  7. NameSpacePrefix = AppSettings.GetString("NameSpacePrefix"),
  8. DefaultDB = 13
  9. }; redisFactory.Init(); container.Register<IRedisFactory>(redisFactory);}}

redis工厂使用

  1. public class MyService
  2. {
  3. private IRedisFactory cacheClient = HostContext.TryResolve<IRedisFactory>();
  4. public object SomeMethod(string key) => cacheClient.Get<object>(key);
  5. }

我有一个redisfactory::execute中的重试函数。我注意到第一次尝试将抛出如下异常,但第二次尝试将成功。

  1. ServiceStack.Redis.RedisResponseException: Unknown reply on integer response: 43OK
  2. at ServiceStack.Redis.RedisNativeClient.ReadLong()
  3. at ServiceStack.Redis.RedisNativeClient.SendReceive[T](Byte[][] cmdWithBinaryArgs, Func`1 fn, Action`1 completePipelineFn, Boolean sendWithoutRead)
  4. at ServiceStack.Redis.RedisNativeClient.SendExpectLong(Byte[][] cmdWithBinaryArgs)
  5. at ServiceStack.Redis.RedisClient.ContainsKey(String key)
  6. at RedisLibrary.RedisFactory.<KeyExisted>b__30_0(String k)
  7. ServiceStack.Redis.RedisResponseException: Zero length response
  8. at ServiceStack.Redis.RedisNativeClient.ParseSingleLine(String r)
  9. at ServiceStack.Redis.RedisNativeClient.SendReceive[T](Byte[][] cmdWithBinaryArgs, Func`1 fn, Action`1 completePipelineFn, Boolean sendWithoutRead)
  10. at ServiceStack.Redis.RedisNativeClient.SendExpectData(Byte[][] cmdWithBinaryArgs)
  11. at ServiceStack.Redis.RedisClient.<>c__DisplayClass131_0`1.<Get>b__0(RedisClient r)
  12. at ServiceStack.Redis.RedisClient.Exec[T](Func`2 action)
  13. at RedisLibrary.RedisFactory.<Get>b__31_0[T](String k)

这只发生在containskey和get操作中。添加、删除或替换仍在正常工作。
需要注意的一点是,自从我们更改redis服务器配置后,在生产中发现了以下错误:
//redis服务器配置更改

  1. Fail over timeout redis -cluster 5000 ->15000
  2. Tcp-keepalive 0 ->300
  3. Repl -blacklog-size 10mb -> 50mb

我尝试在测试环境中用与生产环境中相同的redis配置重现这个问题,但失败了。我还一直在寻找其他类似的问题,例如在servicestack中共享相同的redis客户端。redis client unknown reply on integer response:430k,但没有任何帮助。
有人能帮我指出我的实现或redis配置有什么问题吗?谢谢你的帮助。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题