我们有一个windows服务,它每分钟运行一个quartz作业来处理3个多小时前提交的评论。应用程序使用最新的servicestack.redis v3库与另一台计算机上的redis 2.8.12实例接口。
提交新的评论时,新评论的id存储在redis中的排序集中,我们使用new review.datecreated.ticks作为分数。当作业运行时,它执行以下代码以获取要处理的审阅列表:

using (var redisClient = RedisClientManager.GetClient())
{
    ...
    var cutOff = DateTime.Now.AddHours(-3);
    redisClient.GetRangeFromSortedSetByLowestScore("pending_reviews", 0L, cutOff);
    ...
}

正常情况下,这工作正常,如果在3小时或3小时以前的排序集中有任何评论,则返回它们的id,作业将正常处理它们。但是,相同的确切代码将间歇性地导致发生以下异常:
ServiceStack.Redis.RedisResponseException: Unknown reply on multi-request: ...
at ServiceStack.Redis.RedisNativeClient.CreateResponseError(String error)
at ServiceStack.Redis.RedisNativeClient.ReadMultiData()
at ServiceStack.Redis.RedisNativeClient.SendExpectMultiData(Byte[][] cmdWithBinaryArgs)
at ServiceStack.Redis.RedisNativeClient.GetRangeByScore(Byte[] commandBytes, String setId, Int64 min, Int64 max, Nullable`1 skip, Nullable`1 take, Boolean withScores)
at ServiceStack.Redis.RedisNativeClient.ZRangeByScore(String setId, Int64 min, Int64 max, Nullable`1 skip, Nullable`1 take)
at ServiceStack.Redis.RedisClient.GetRangeFromSortedSetByLowestScore(String setId, Int64 fromScore, Int64 toScore, Nullable`1 skip, Nullable`1 take)
at ServiceStack.Redis.RedisClient.GetRangeFromSortedSetByLowestScore(String setId, Int64 fromScore, Int64 toScore)

我试着下载并进入servicestack源代码,但在调试时,这个问题从未发生过,而且我似乎无法复制它。redisclientmanager是一个单一的pooledredisclientmanager,据我所知,我正在正确地创建和处理客户端,而且我也没有使用事务或管道。
我的理解是,池客户机管理器正在做一些棘手的连接共享工作,因为redis实际上是单线程的。感觉它可能是从另一个连接返回了错误的结果,或者其他线程或连接共享问题返回了错误的结果。
有什么可能导致这种情况的想法吗?

最佳答案

好吧,我想出来了。
稍后在作业中,在检索id之后,它实际上使用了一个事务。当我更仔细地检查事务代码时,我意识到多个客户机调用是在单个queuecommand的上下文中进行的。虽然在初始作业调用期间没有发生错误,但在作业下次运行时,它将始终得到错误。
所以我只是将每个客户机调用分解成自己的queuecommand,然后,错误消失了。经验教训:在使用事务/管道时,请非常小心,每个redis客户机调用都在自己的专用queuecommand中!在我的情况下,它被隐藏在一个助手的方法,我不得不挖一点找到它。

关于multithreading - RedisResponseException:多请求的未知回复,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30745681/

10-15 10:09