Redis Cluster的可扩展性使用Jedis 2.8.0来测试吞吐量

时间:2016-03-21 15:02:25

标签: java multithreading performance redis jedis

我在N个线程之间共享一个JedisCluster实例,执行set操作。

当我使用64个线程运行时,设置操作的吞吐量仅略微增加(与使用8个线程运行相比)。

如何使用JedisCluster配置GenericObjectPoolConfig实例,以便在增加线程数时最大化吞吐量?

我试过了

 GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
 poolConfig.setMaxTotal(64);

 jedisCluster = new JedisCluster(jedisClusterNodes, poolConfig);

认为这可能会增加jedisCluster与群集连接的数量,从而提高吞吐量。

但是,我发现效果很小。

1 个答案:

答案 0 :(得分:1)

在谈论表现时,我需要先深入了解一些细节,然后才能真正回答你的问题。

一种天真的方法表明:线程(并发)越多,吞吐量越高。

我的陈述没错,但事实并非如此。并发和由此产生的性能不是(总是)线性的,因为幕后有很多涉及。从顺序处理到并发处理可能会导致执行两次工作的事情与顺序执行相比。此示例假定您运行多核计算机,该计算机未被其他任何内容占用,并且它具有足够的带宽用于所需的工作处理(I / O,网络,内存)。如果您将此示例从两个线程扩展到八个,但您的计算机只有四个物理核心,则可能会发生奇怪的事情。

首先,处理器需要调度两个线程,因此每个线程的行为可能就像它们将按顺序运行一样,除了进程,操作系统和处理器增加了开销,因为线程数是内核的两倍。编排这些人的代价是至少需要在内存分配和CPU时间内支付。如果工作负载需要大量I / O,那么工作处理可能会受到I / O带宽的限制,并且同时运行可能会增加吞吐量,因为CPU大部分都在等待I / O返回要处理的数据。在那种情况下,4个线程可能被I / O阻塞,而其他4个线程正在做一些工作。类似适用于您的应用程序使用的内存和其他资源。实际上,还有更多内容涉及上下文切换,分支预测,L1 / L2 / L3缓存,锁定以及足以编写500页书籍的内容。让我们保持基本水平。

资源共享和某些限制会导致不同的可伸缩性配置文件。有些是线性的,直到一定的并发级别,有些是在同一吞吐量中增加更多的并发结果,有些人在添加并发性时因为$reasons而变得更慢。

Effects on scalability

现在,我们可以分析Redis,Redis Cluster和并发性是如何相关的。

  • Redis是一种需要网络I / O的网络服务。网络可能是显而易见的,但我们需要在我们的考虑因素中添加这一事实,这意味着Redis服务器与在同一主机上运行的其他东西以及使用交换机,路由器,集线器等的东西共享其网络连接。同样适用于客户端,即使是在你进行测试时你告诉其他人不要跑任何东西的情况。

  • 接下来,Redis使用单线程处理模型来完成用户任务(不想深入了解后台I / O,无内存释放和异步复制)。所以你可以假设Redis使用一个CPU核心来完成它的工作,但事实上,它可以使用更多。如果多个客户端一次发送命令,Redis按照到达顺序依次处理命令(阻塞操作除外,但让我们留下这个帖子)。如果在一台计算机上运行N Redis实例,其中N也是CPU核心数,则可以轻松地再次运行到共享方案中 - 这是您可能希望避免的。

  • 您有一个或多个客户端与您的Redis服务器通信。根据测试中涉及的客户端数量,这会产生影响。在8核计算机上运行64个线程可能不是最好的主意,因为一次只能有8个核心可以执行工作(让我们离开超线程,所有这些都不在这里,不要混淆你太多了)。请求超过8个线程会导致分时效应。为Redis和其他网络服务运行多于线程的线程并不是一个太糟糕的想法,因为I / O(网络)总会有一些开销/延迟。您需要从Java(通过JVM,操作系统,网络适配器,路由器)向Redis(路由器,网络,yadda yadda yadda)发送数据包,Redis必须处理命令并发回响应。这通常需要一些时间。

  • 客户端本身(假设一个JVM上的并发)锁定某些资源以进行同步。特别是使用现有/创建新连接请求新连接是锁定的方案。您已找到Pool配置的链接。当一个线程锁定资源时,没有其他线程可以访问该资源。

了解基础知识,我们可以深入研究如何使用jedis和Redis Cluster测量吞吐量:

  • Redis群集上的拥塞可能是个问题。如果所有客户端线程正在与同一群集节点通信,则其他群集节点处于空闲状态,您可以有效地测量一个节点的行为而不是群集:解决方案:创建均匀工作负载(级别:硬!)

  • 客户端拥塞:在8核计算机上运行64个线程(这只是我在这里的假设,所以如果我错了请不要打败我)不是最好的主意。将客户端上的线程数提高一点,高于Cluster节点的数量(假设每个群集节点的工作负载均匀),并且超过CPU内核数量可以提高性能,这绝不是一个太糟糕的主意。拥有8个线程(与CPU核心数相比)是一种过度杀伤,因为它增加了所有级别的调度开销。通常,性能工程与找到工作,开销,带宽限制和并发之间的最佳比率有关。因此,找到最佳线程数是计算机科学中的一个自己的领域。

  • 如果使用运行多个总线程的多个系统运行测试,则可能比从一个系统运行测试更接近生产环境。分布式性能测试是一个主类(级别:非常难!)这里的技巧是监视测试使用的所有资源,确保没有任何过载或找到识别特定资源限制的临界点。监控客户端和服务器只是简单的部分。

由于我不知道您的设置(Redis群集节点的数量,在不同服务器之间分发群集节点,在测试期间加载Redis服务器,客户端和网络,而不是由您的测试引起的其他因素),它是无法说出原因是什么。