Python / Redis Multiprocessing - PullRequest
       13

Python / Redis Multiprocessing

5 голосов
/ 14 декабря 2010

Я использую Pool.map из многопроцессорной библиотеки для итерации большого XML-файла и сохранения количества слов и ngram в набор из трех серверов redis. (которые полностью хранятся в памяти) Но по какой-то причине все 4 ядра процессора все время простаивают на 60%. На сервере достаточно оперативной памяти, и iotop показывает, что ввода-вывода диска не происходит.

У меня 4 потока Python и 3 сервера Redis, работающих в качестве демонов на трех разных портах. Каждый поток Python подключается ко всем трем серверам.

Количество операций redis на каждом сервере значительно ниже того, на которое он рассчитан.

Я не могу найти узкое место в этой программе? Какими будут вероятные кандидаты?

1 Ответ

4 голосов
/ 17 апреля 2011

Сетевая задержка может влиять на время простоя процессора в клиентском приложении Python.Если задержка в сети между клиентом и сервером составляет всего 2 миллисекунды, и вы выполняете 10 000 команд redis, ваше приложение должно простаивать не менее 20 секунд, независимо от скорости любого другого компонента.

ИспользованиеНесколько потоков Python могут помочь, но каждый поток все равно будет простаивать, когда команда блокировки отправляется на сервер.Если у вас не очень много потоков, они часто синхронизируются и все блокируют ожидание ответа.Поскольку каждый поток подключается к всем трем серверам, шансы на это уменьшаются, за исключением случаев, когда все они заблокированы в ожидании одного и того же сервера.

Предполагается, что у вас естьравномерный случайный распределенный доступ через серверы для обслуживания ваших запросов (путем хеширования имен ключей для реализации разделения или разбиения), тогда вероятность того, что три случайных запроса будут хэшироваться на один и тот же сервер redis, обратно пропорциональна количеству серверов.Для 1 сервера 100% времени вы будете хэшировать на одном и том же сервере, для 2 - 50% времени, для 3 - 33% времени.Может случиться так, что в 1/3 времени все ваши потоки блокируются в ожидании одного и того же сервера.Redis является однопоточным при обработке операций с данными, поэтому он должен обрабатывать каждый запрос один за другим.Ваше наблюдение о том, что загрузка вашего ЦП достигает только 60%, согласуется с вероятностью того, что все ваши запросы будут заблокированы из-за задержки в сети к одному и тому же серверу.

Продолжая предположение о том, что вы реализуете сегментирование на стороне клиента путем хэширования имен ключейвы можете устранить конфликт между потоками, назначив каждому потоку отдельное соединение с сервером, и оценить хэш-раздел, прежде чем передавать запрос в рабочий поток.Это гарантирует, что все потоки ожидают при различной задержке в сети.Но может быть даже лучшее улучшение при использовании конвейерной передачи.

Вы можете уменьшить влияние задержки в сети, используя функцию конвейера модуля redis-py , если вам не нужнонемедленный результат от сервера.Это может быть жизнеспособным для вас, так как вы, кажется, сохраняете результаты обработки данных в redis.Чтобы реализовать это с помощью redis-py, периодически получайте дескриптор конвейера к существующему объекту подключения redis, используя метод .pipeline(), и вызывайте несколько команд хранилища для этого нового дескриптора так же, как и для основного объекта подключения redis.Redis.Затем вызовите .execute(), чтобы заблокировать ответы.Вы можете улучшить порядок на несколько порядков, используя конвейеризацию для пакетирования десятков или сотен команд.Ваш клиентский поток не будет блокироваться, пока вы не введете последний метод .execute() для дескриптора конвейера.

Если вы примените оба изменения, и каждый рабочий поток связывается только с одним сервером, конвейеризуя несколько команд вместе (по крайней мере,5-10, чтобы увидеть значительный результат), вы можете увидеть большее использование процессора в клиенте (ближе к 100%).Cpython GIL по-прежнему будет ограничивать клиента одним ядром, но похоже, что вы уже используете другие ядра для синтаксического анализа XML с помощью модуля многопроцессорной обработки.

Существует хорошая запись о конвейерной обработке на сайте redis.io.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...