Open Darkhan97 opened 5 years ago
We had this problem and solved it. What appears to be the issue is code like either of the following examples.
val clientOutOfScope = redisPool.withClient { client =>
client
}
clientOutOfScope.get(...)
redisPool.withClient { client =>
Future {
client.get(...)
}
}
In both cases, the client
is used in a situation where it is no longer in the withClient
block, either used outside the block or in an asynchronous piece of code. At this point, the withClient
block is finished and the client has been returned to the pool. If another thread then tries to use the pool, it may acquire the same client from the pool and the client will be shared across threads. This causes an internal buffer to get mixed up and results in the error above. It can also result in get
, hget
calls returning the value of a different key than the one requested.
Solution: do not use async code within withClient
and never pass the client outside of its body scope.
object RedisConnectionUtil extends RedisServiceProvider { lazy val _redisMasterClientPool = new RedisClientPool(redisMasterUrl, 6379) override def getRedisMasterClientPool(): RedisClientPool = _redisMasterClientPool } trait RedisCacheService { def insert(key: CacheKey, values: List[String]): Boolean = { val redisPool = redisConnectionUtil.getRedisMasterClientPool() try { redisPool.withClient(client => { client.auth(redisConnectionUtil.getRedisAuth()) values.foreach(value => { client.lpush(key, value) }) }) logInfo(s"REDIS, push to cache successful for ${key}, values size = ${values.size}") } catch { case e: Exception => { logError(s"Exception while pushing to Redis, key = ${key} message = ${e.getMessage}", e)
}
}
}
I am using the redis client like this, still getting above error. Can you help me find out what is the issue?
I don't see any problem with that code... Perhaps consider writing a minimal example with a test, and posting it to GitHub so it's reproducible.
Yes, a minimal reproducible test case will help debug the problem.
@Oduig Indeed .. a client
escaping the scope of withClient
is a problem.
I just bumped into this issue because I was sending a list of items to redis in batches with list.grouped(500)
... but forgot that grouped returns an Iterator that is "lazy" and doesn't comprehend the list until you call .toList
. I was doing that outside the withClient
block and therefore this error occurred. Very subtle!
@Oduig Thank you. it working,
// "Sometimes" Protocol error found code
private val redisClient = pool.withClient { client => client }
def jwtBlackList(key: Long, authObject: String) = {
redisClient.rpush(key, authObject)
redisClient.expire(key, 240)
}
use only withClient "inside".
// Code changed after seeing your GitHub answer
def jwtBlackList(key: Long, authObject: String) = {
pool.withClient { redisClient =>
redisClient.rpush(key, authObject)
redisClient.expire(key, 240)
}
}
Now my code doesn't cause protocol errors.
@debasishg I've got a exception similar to the which is = "java.lang.Exception: Protocol error: Got ($,[B@1669a570) as initial reply byte". I am using Redis server v=4.0.9, clitent "net.debasishg" %% "redisclient" % "3.9". Exception was raised from here !!! val scanTri:Option[(Option[Int], Option[List[Option[String]]])] = try { r.hscan(key, cursor, s"${text}*", 500) } catch { case e:Exception => { println("Cosyak = " + e) None } } How can I deal with this?