gpt4 book ai didi

Python/Redis 多处理

转载 作者:IT王子 更新时间:2023-10-29 05:58:19 25 4
gpt4 key购买 nike

我正在使用多处理库中的 Pool.map 遍历大型 XML 文件,并将单词和 ngram 计数保存到一组三个 Redis 服务器中。 (完全位于内存中)但由于某种原因,所有 4 个 cpu 内核一直处于 60% 左右的闲置状态。服务器有足够的 RAM,iotop 显示没有磁盘 IO 发生。

我有 4 个 python 线程和 3 个 redis 服务器在三个不同的端口上作为守护进程运行。每个 Python 线程都连接到所有三个服务器。

每台服务器上的 Redis 操作数量远低于其基准测试能力。

我找不到这个程序的瓶颈?可能的候选人有哪些?

最佳答案

网络延迟可能会影响您的 Python 客户端应用程序中的空闲 CPU 时间。如果客户端到服务器之间的网络延迟甚至低至 2 毫秒,并且您执行 10,000 个 redis 命令,则无论任何其他组件的速度如何,您的应用程序都必须闲置至少 20 秒。

使用多个 Python 线程会有所帮助,但当向服务器发送阻塞命令时,每个线程仍会空闲。除非你有很多线程,否则它们通常会同步并全部阻塞等待响应。因为每个线程都连接到所有 三个服务器,所以发生这种情况的机会减少了,除非所有线程都被阻塞等待同一台服务器。

假设您有跨服务器的统一随机分布式访问来服务您的请求(通过散列键名来实现分片或分区),那么三个随机请求将散列到同一个 redis 的几率服务器与服务器数量成反比。对于 1 个服务器,100% 的时间你会散列到同一台服务器,2 个是 50% 的时间,3 个是 33% 的时间。可能发生的情况是,有 1/3 的时间,您的所有线程都被阻塞,等待同一台服务器。 Redis 在处理数据操作时是单线程的,所以它必须一个接一个地处理每个请求。您观察到您的 CPU 利用率仅达到 60%,这与您的请求因对同一服务器的网络延迟而全部被阻止的可能性一致。

继续假设您正在通过对键名称进行散列来实现客户端分片,您可以通过为每个线程分配一个服务器连接来消除线程之间的争用,并在将请求传递给工作线程之前评估分区散列。这将确保所有线程都在等待不同 网络延迟。但是使用流水线可能会有更好的改进。

您可以使用 the redis-py module 的管道功能来减少网络延迟的影响。 ,如果您不需要服务器的立即结果。这对你来说可能是可行的,因为你似乎将数据处理的结果存储到 redis 中。要使用 redis-py 实现此功能,请使用 .pipeline() 定期获取现有 redis 连接对象的管道句柄。方法并针对该新句柄调用多个存储命令,就像对主 redis.Redis 连接对象所做的一样。然后调用 .execute()阻止回复。通过使用流水线将数十或数百个命令批处理在一起,您可以获得数量级的改进。在您发出最终 .execute() 之前,您的客户端线程不会阻塞管道句柄上的方法。

如果您同时应用这两项更改,并且每个工作线程只与一台服务器通信,将多个命令流水线化在一起(至少 5-10 条才能看到明显的结果),您可能会看到客户端的 CPU 使用率更高(接近 100% ). cpython GIL 仍将客户端限制为一个核心,但听起来您已经在使用多处理模块使用其他核心进行 XML 解析。

有一个good writeup about pipelining在 redis.io 网站上。

关于Python/Redis 多处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4441886/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com