为什么单一连接到redis表现不好以及如何使其更快

时间:2015-01-16 07:13:37

标签: c performance networking redis benchmarking

我最近正在对redis进行基准测试,这是我得到的结果:

ubuntu 13.10 x86_64 with kernel version 3.11, 
Intel® Core™ i5 CPU M 430 @ 2.27GHz × 4
8GB Memory

enter image description here

因此,在相同的负载下,与redis的多次连接可以比单次连接快8倍。我不是在考虑流水线,我已经在我的测试中尝试了很多优化方法。 (使用taskset使redix在单核中运行,使用unix域套接字)

两个问题:

  1. 为什么多次连接redis可以比单连接更快地执行此操作?

  2. 有没有其他方法(管道除外)在单一连接下提高性能?

1 个答案:

答案 0 :(得分:1)

我最近对这个问题进行了一些性能测试,并在这里得到了一些结果。

关键是要确定单连接案例的额外延迟来自何处。我的第一个假设是他们来自epoll。为了找到答案,我使用systemtapscript to determine epoll latency。结果(上面:1个连接结果,下面:10个连接结果。对不起,图片中的单位应该是纳秒):

enter image description here

从结果中,您可以看到保持epoll的平均时间几乎相同,8655纳秒对10254纳秒。但是,总数存在显着差异。对于10连接我们称epoll等待444528次,但我们将在单连接情况下将其称为2000054次,这是4倍,这是导致额外时间使用的原因。

接下来的问题就是为什么我们在多重连接期间调用epoll以减少时间。在用redis源代码进行了一些探索之后,我找到了原因。 epoll每次返回时,都会返回它要处理的事件数。 presudo代码就像(隐藏了大部分细节):

fds = epoll_wait(fds_we_are_monitoring);
for fd in fds:
    handle_event_happening_in(fd);

返回值fds是发生IO的所有事件的集合,例如,从socket读取输入。对于单连接基准,fds_we_are_monitoring为1,因为只有一个连接,然后每次#fd为1.但对于10连接情况,fds可以返回任何小于10的数字,然后在for loop中一起处理事件。我们从epoll一次返回的事件越多,我们就能越快得到。因为请求总数是固定的,所以在这种情况下,1M设置请求。

为了验证这一点,我使用systemtap绘制函数返回值的分布。 aeProcessEvents,返回它处理的事件数。

enter image description here

我们可以看到单连接情况下的平均值:1和10连接情况下的7。这证明了我们的假设,即epoll返回的事件数量越多,我们处理请求的速度就越快,直到它受到CPU限制。

我想我得到了第一个问题的答案:为什么多次连接到redis可以比单一连接更快地执行此操作。但是,我仍然想知道是否有任何其他方式(管道除外)在单一连接下提高性能。如果有其他人可以分享一些想法,我将不胜感激。