1

我正在使用 Ruby 1.8.7 和 redis-rb gem。我尝试了各种方法将 100 万条记录写入 Redis 列表。

我注意到当我使用线程时性能会受到影响。这是什么原因,我该如何预防?我将在线程环境中使用 Redis 进行生产,所以我很担心。

这是我的结果:

1_000_000.times do
  $r.rpush "test_list", rand(1_000_000)
end
# Took: 74.2986769676208 sec.

threads = []
1_000.times do
  threads << Thread.new {
    1_000.times {
      $r.rpush "test_list", rand(1_000_000)
    }
  }
end
threads.each { |k| k.join }
# Took: 391.705540895462 sec.

mutex = Mutex.new
threads = []
1_000.times do
  threads << Thread.new {
    1_000.times {
      mutex.synchronize {
        $r.rpush "test_list", rand(1_000_000)
      }
    }
  }
end
threads.each { |k| k.join }
# Took: 308.474660873413 sec.

mutex = Mutex.new
threads = []
10.times do
  threads << Thread.new {
    100_000.times {
      mutex.synchronize {
        $r.rpush "test_list", rand(1_000_000)
      }
    }
  }
end
threads.each { |k| k.join }
# Took: 109.103996992111 sec.

forks = []
8.times do
  forks << fork {
    125_000.times {
      $r.rpush "test_list", rand(1_000_000)
    }
  }
end
forks.each { |k| Process.wait(k) }
# Took: 23.7934968471527 sec.
4

1 回答 1

0

撞!

这是一个非常好的例子,因为它展示了很多场景。我们是否应该假设正确数量的条目最终出现在 redis 上的“test_list”中,因为我想知道第一个示例......?(在线程加入后查看计数会很有用)

所以,我的解释:

1 个线程,每个 100 万次写入

执行时间:74秒

使用序列化写入到 redis 的单一连接

1000 个线程,每个 100 次写入,没有 ruby​​ 互斥锁

执行时间:380秒

我认为我们必须假设 Redis 使用它自己的互斥锁进行写入,所以这里的“开销”将是 Redis 自己的互斥锁的结果。这可能是因为每个线程共享相同的客户端对象来写入 - 你是否尝试创建 1000 个 redis 客户端?:)

1000 个线程,每个 1000 次写入,红宝石互斥锁

执行时间:308 秒

由于互斥锁位于 ruby​​ 线程中,因此对 Redis 的写入(“设置”)看起来更加有序。这里的开销是必须等待 1 个线程写入 Redis 的 999 个线程......

10 个线程,每个 100,000 次写入,本地互斥锁

执行时间:108 秒

每次等待互斥锁的线程更少,因此写入周期更快。

8 个分叉,每个分叉 125,000 次写入

执行时间:23秒

这里仍然有一点开销,但除此之外,这是 8 个不同的 Redis 连接,每个连接写入 125,000 个键。Redis 把它圈起来......我认为“开销”在 ruby​​ 进程的分叉中(否则你会期望更像 10 秒)

感谢您进行测试 - 它真的很有指导意义,我将把它作为训练练习展示给我们的开发人员!

于 2014-10-01T00:35:19.053 回答