【问题标题】:Trouble using Threading with Redis (Jedis) in Scala在 Scala 中使用带有 Redis (Jedis) 的线程时遇到问题
【发布时间】:2021-09-11 10:42:49
【问题描述】:

我有一个使用线程(实际上是 Spark)和 Redis(Jedis)的 Scala 程序。我为我的 Redis 操作定义了一个object,其中我有一个用于连接的Lazy val。我需要每个线程打开到 Redis 的连接并并行使用它。
连接对象:

object redisOp{
  lazy val r = new Jedis("127.0.0.1",6379,30)
  def find(u: Long): Option[Long] = Option(r.get(s"p$u")).flatMap(p => if (p.toLong == u) Some(u) else find(p.toLong))
  // and other functions
}

当我将它与一个线程一起使用时,它运行良好。但是当多个线程使用它时,我得到了错误。起初,我在每个线程中都得到了Unknown replay: 4,其中“4”是一个随机字符(redis.clients.jedis.exceptions.JedisConnectionException: Unknown reply:)。
然后从redis-cli 开始,我尝试设置config set timeout 3000030000,因为我还在日志中看到了redis.clients.jedis.exceptions.JedisConnectionException: Unexpected end of stream 和有时redis.clients.jedis.exceptions.JedisDataException: ERR Protocol error: invalid multibulk length。现在在某些运行中(当切换到 2 个线程而不是 4 个线程时),程序永远卡在一个阶段而没有错误!我检查了 Spark-UI 以检查执行程序的日志,但找不到任何有用的信息:https://pastebin.com/iJMeBD0D

我认为问题在于定义和使用与 Redis 的连接。另外,如果需要,请告诉我关闭连接的正确方法。

【问题讨论】:

  • 恕我直言,您应该创建一个新问题(仅包含更新的部分),而不是更新问题。

标签: multithreading scala apache-spark redis jedis


【解决方案1】:

Jedis 对象不是线程安全的。您应该在多线程环境中使用某种对象/连接池。 Jedis 为此提供了 JedisPool。更多详情请见Jedis Wiki

基本思路是通过JedisPool.getResource()获取Jedis对象,通过Jedis.close()返回该对象。

【讨论】:

  • 谢谢。所以我将在我的单例中有一个“池”实例,然后对于每个函数,我首先getResource(),做这项工作,然后.close 它,对吗?每个线程通过每个函数调用打开/关闭连接的成本不是很高吗?
  • 连接不会在每次函数调用时打开/关闭,而是会被重用。如果 Jedis 是 JedisPool 的一部分,在门后,.close() 实际上不会关闭连接,但会声明它可以免费重用。它 (.close) 包含在此过程中以利用 Java 的 try-with-resource 范例。
  • 我仍然有问题需要增加.setMaxIdle(8000).setMaxTotal(8000) 否则程序会卡住!我需要帮助!这是我现在的连接:pastebin.com/Z8LKuXTF
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-08
  • 1970-01-01
  • 2011-12-02
  • 1970-01-01
相关资源
最近更新 更多