我们有一个Windows服务,每分钟运行一次石英作业,以处理超过3小时前提交的评论。该应用程序使用最新的ServiceStack.Redis v3库与另一台机器上的Redis 2.8.12实例进行交互。
当提交新评论时,新评论的ID存储在Redis中的有序集中,我们使用 NewReview.DateCreated.Ticks 作为评分。作业运行时,它会执行以下代码以获取要处理的评论列表:
using (var redisClient = RedisClientManager.GetClient())
{
...
var cutOff = DateTime.Now.AddHours(-3);
redisClient.GetRangeFromSortedSetByLowestScore("pending_reviews", 0L, cutOff);
...
}
通常情况下,这样可以正常工作,如果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实际上是单线程的,因此汇集的客户端管理器正在进行一些棘手的连接共享。感觉它可能从另一个连接或其他一些线程或连接共享问题返回错误的结果。
关于可能导致这种情况的任何想法?
答案 0 :(得分:0)
好的我明白了。
稍后在工作中,在检索到ID之后,它实际上是在使用事务。当我更仔细地审查事务代码时,我意识到在单个QueueCommand的上下文中正在进行多个客户端调用。虽然在初始作业调用期间没有发生错误,但是下次作业运行时总是会出错。
所以我简单地将每个客户端呼叫分解为自己的QueueCommand和Voila,错误就消失了。获得的经验:当使用事务/管道时要非常小心,每个redis客户端调用都在它自己的专用QueueCommand中!在我的情况下,它隐藏在一个辅助方法中,我不得不挖掘一下来找到它。