【问题标题】:Scalability of Redis Cluster using Jedis 2.8.0 to benchmark throughputRedis 集群的可扩展性使用 Jedis 2.8.0 来基准吞吐量
【发布时间】:2016-07-08 04:05:10
【问题描述】:
我有一个JedisCluster 的实例在 N 个执行集合操作的线程之间共享。
当我使用 64 个线程运行时,set 操作的吞吐量仅略有增加(与使用 8 个线程运行相比)。
如何使用GenericObjectPoolConfig 配置JedisCluster 实例,以便在增加线程数时最大化吞吐量?
我试过了
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(64);
jedisCluster = new JedisCluster(jedisClusterNodes, poolConfig);
相信这可以增加与集群的 jedisCluster 连接数量,从而提高吞吐量。
但是,我观察到的影响很小。
【问题讨论】:
标签:
java
multithreading
performance
redis
jedis
【解决方案1】:
在谈论性能时,我们需要深入研究一下细节,然后才能真正回答您的问题。
一种天真的方法表明:线程(并发)越多,吞吐量就越高。
我的说法没有错,但也不是真的。并发性和由此产生的性能并不是(总是)线性的,因为幕后涉及的东西太多了。与顺序执行相比,将某些内容从顺序处理转变为并发处理可能会导致执行两倍的工作。这个例子假设你运行一个多核机器,它没有被其他任何东西占用,并且它有足够的带宽来处理所需的工作处理(I/O、网络、内存)。如果您将此示例从两个线程扩展到八个,但您的机器只有四个物理内核,则可能会发生奇怪的事情。
首先,处理器需要调度两个线程,因此每个线程的行为可能就像它们将按顺序运行一样,除了进程、操作系统和处理器由于线程数是内核的两倍而导致开销增加.协调这些人需要付出至少在内存分配和 CPU 时间方面的成本。如果工作负载需要大量 I/O,那么工作处理可能会受到 I/O 带宽的限制,同时运行的东西可能会增加吞吐量,因为 CPU 大部分时间都在等待 I/O 返回要处理的数据。在这种情况下,4 个线程可能会被 I/O 阻塞,而其他 4 个线程正在做一些工作。类似的情况适用于您的应用程序使用的内存和其他资源。实际上,还有更多内容深入到上下文切换、分支预测、L1/L2/L3 缓存、锁定等等,足以编写一本 500 页的书。让我们停留在基本水平。
资源共享和某些限制导致不同的可扩展性配置文件。有些在达到一定的并发水平之前是线性的,有些达到顶峰并添加更多的并发会导致相同的吞吐量,有些在添加并发时会因为$reasons而变得更慢。
现在,我们可以分析一下 Redis、Redis Cluster 和并发之间的关系。
Redis 是一种需要网络 I/O 的网络服务。网络可能很明显,但我们需要将这一事实添加到我们的考虑中,这意味着 Redis 服务器与运行在同一主机上的其他事物以及使用交换机、路由器、集线器等的事物共享其网络连接。同样适用于客户端,即使在您告诉其他人在测试时不要运行任何东西的情况下。
接下来是,Redis 对用户任务使用单线程处理模型(不想深入研究后台 I/O、惰性内存释放和异步复制)。所以你可以假设 Redis 使用一个 CPU 内核来工作,但事实上,它可以使用更多。如果多个客户端同时发送命令,Redis 会按到达的顺序依次处理命令(阻塞操作除外,但本文暂且不提)。如果你在一台机器上运行 N 个 Redis 实例,其中 N 也是 CPU 内核的数量,你可以很容易地再次运行到共享场景中——这是你可能想要避免的。
您有一个或多个客户端与您的 Redis 服务器通信。根据测试中涉及的客户端数量,这会产生影响。在 8 核机器上运行 64 个线程可能不是最好的主意,因为一次只有 8 个核可以执行工作(让我们把超线程和所有这些都放在外面,不想让你太困惑)。请求超过 8 个线程会导致分时效果。为 Redis 和其他网络服务运行比 CPU 内核多 bit 的线程并不是一个坏主意,因为 I/O(网络)总是存在一些开销/延迟。您需要将数据包从 Java(通过 JVM、操作系统、网络适配器、路由器)发送到 Redis(路由器、网络、yadda yadda yadda),Redis 必须处理命令并发送回响应。这通常需要一些时间。
客户端本身(假设在一个 JVM 上并发)锁定某些资源以进行同步。特别是使用现有/创建新连接来请求新连接是一种锁定方案。您已经找到了指向池配置的链接。当一个线程锁定一个资源时,没有其他线程可以访问该资源。
了解基础知识后,我们可以深入研究如何使用 jedis 和 Redis Cluster 来衡量吞吐量:
-
Redis 集群上的拥塞可能是一个问题。如果所有客户端线程都在与同一个集群节点通信,则其他集群节点处于空闲状态,并且您有效地测量了一个节点的行为而不是集群:解决方案:创建一个均匀的工作负载(级别:困难!)
李>
客户端拥塞:在 8 核机器上运行 64 个线程(这只是我的假设,所以如果我错了请不要打我)不是最好的主意。将客户端上的线程数量提高到略高于集群节点的数量(假设每个集群节点的工作负载均匀)和稍微高于 CPU 内核的数量可以提高性能,这绝不是一个坏主意。拥有 8 个线程(与 CPU 内核的数量相比)是一种过度杀伤力,因为它会增加所有级别的调度开销。一般来说,性能工程与找到工作、开销、带宽限制和并发性之间的最佳比率有关。因此,找到最佳线程数是计算机科学的一个领域。
如果使用多个系统运行测试,即运行多个总线程,则可能比从一个系统运行测试更接近生产环境。分布式性能测试是一门大师课(级别:非常难!)这里的技巧是监视测试使用的所有资源,确保没有任何东西过载或找到确定特定资源限制的临界点。监控客户端和服务器只是简单的部分。
由于我不知道您的设置(Redis Cluster 节点的数量、Cluster 节点在不同服务器之间的分布、Redis 服务器上的负载、客户端和测试期间的网络,这是由您的测试以外的其他因素引起的),所以它是不可能说是什么原因。