【问题标题】:ruby safe way to run multiple threads运行多个线程的红宝石安全方法
【发布时间】:2019-12-06 11:31:20
【问题描述】:

我有一项服务可以读取文件 CSV 上的所有行,然后导入数据库。该过程只是读取文件并写入数据库,无需在数据库上查找或更新。所以我想通过代码加快这个过程:

CSV.foreach(@file.path, encoding: 'BOM|UTF-8:UTF-8', headers: true).each do |row|
  # start thread i
  Record.create(row)
  # end thread i
end

我希望它使用多个线程运行,并且将这些限制数量限制为 10 个线程以保持服务器的 RAM 不会占用太多。 我尝试使用Concurrent::FixedThreadPool,但它有时会失去与数据库的连接,尽管我只是设置了 5 个线程运行

关于安全线程运行的任何想法?

【问题讨论】:

  • 您是否考虑过使用导入工具数据库将 CSV 作为整个文件导入,而不是使用 Ruby 逐行插入文件?
  • 实际上,我从 CSV 读取数据,然后使用一些过滤器列插入到集合 B。例如,年龄必须大于 18 岁并且居住在大城市
  • 我明白,但是即使导入到临时表,然后在某些条件下复制到最终表中并删除临时表,在纯 SQL 中也应该比在 Ruby 中快几个数量级。
  • 这是个好主意。我会将其应用于代码。此外,我还在继续听安全线程解决方案

标签: ruby-on-rails ruby ruby-on-rails-5


【解决方案1】:

尝试使用互斥锁

mutex = Mutex.new
CSV.foreach(@file.path, encoding: 'BOM|UTF-8:UTF-8', headers: true).each do |row|
  threads = Thread.new do
              mutex.synchronize do
                Record.create(row)
              end
            end 
end
threads.each(&:join)

希望对你有帮助。

【讨论】:

  • 据我所知,Mutex 每次只允许 1 个线程在其内容中运行。所以现在只有1个线程在运行,其他的会等到这个线程跳出Mutex的内容,是不是?
  • 假设 CSV 文件有 2 亿行,它占用的内存会很大,可能会导致内存问题
  • 如果我们在这种情况下使用Mutex,与不使用线程完全一样
  • @Peter_175:请尝试线程池,如果您愿意,我会为您创建示例。另外,我认为在您的情况下,批量插入是值得的,而不是线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-18
  • 2017-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多