Redis однопоточный, тогда как он делает параллельный ввод-вывод?

170

Пытаясь понять некоторые основы Redis, я наткнулся на интересную запись в блоге .

Автор заявляет:

Redis является однопоточным с epoll / kqueue и масштабируется бесконечно с точки зрения параллелизма ввода / вывода.

Я, конечно, неправильно понимаю всю эту многопоточность, потому что считаю это утверждение загадочным. Если программа однопоточная, как она работает одновременно? Почему так здорово, что операции Redis являются атомарными, если сервер так или иначе является однопоточным?

Кто-нибудь может пролить свет на этот вопрос?

Пшемыслав Петшкевич
источник

Ответы:

362

Ну, это зависит от того, как вы определяете параллелизм.

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

Например, бармен может присматривать за несколькими клиентами, в то время как он может готовить только один напиток за раз. Таким образом, он может обеспечить параллелизм без параллелизма.

Этот вопрос обсуждался здесь: в чем разница между параллелизмом и параллелизмом?

Смотрите также эту презентацию от Роба Пайка.

Однопоточная программа может определенно обеспечить параллелизм на уровне ввода / вывода, используя механизм мультиплексирования ввода / вывода и цикл обработки событий (что и делает Redis).

Параллелизм имеет свою стоимость: благодаря наличию нескольких сокетов / нескольких ядер на современном оборудовании синхронизация между потоками чрезвычайно дорога. С другой стороны, узким местом эффективного механизма хранения, такого как Redis, очень часто является сеть, задолго до ЦП. Поэтому изолированные циклы событий (которые не требуют синхронизации) рассматриваются как хороший проект для создания эффективных, масштабируемых серверов.

Тот факт, что операции Redis являются атомарными, является просто следствием однопоточного цикла событий. Интересным моментом является то, что атомарность предоставляется без дополнительной оплаты (не требует синхронизации). Пользователь может использовать его для реализации оптимистической блокировки и других шаблонов, не оплачивая затраты на синхронизацию.

Дидье Специя
источник
135
Хорошая аналогия бармена :)
Серхио Туленцев
3
В этом смысле v4 меняет правила игры - смотрите мой ответ на stackoverflow.com/a/45374864/3160475 :)
Итамар Хабер,
1
единственное, что мне не очень нравится в ответе и сравнении, - это то, что кажется, что параллелизм не работает параллельно, и, скорее всего, это так, как я могу проверить, выполнив асинхронную задачу и выполнив работу, которая в конечном итоге считается параллельно. Параллелизм в контексте этой статьи относится к многоядерному характеру способности работать на множественных потоках. Т.е. почему ссылка на него является поточно-безопасной.
Кристиан Мэтью
Все еще действует в 2020 году?
Роберто Манфреда
21

ОК, Redis является однопоточным на уровне пользователя, OTOH, все асинхронные операции ввода-вывода поддерживаются пулами потоков ядра и / или драйверами двухуровневого уровня.

В некоторых случаях « одновременный » включает в себя распространение сетевых событий на конечные автоматы сокетов. Он однопоточный, работает на одном ядре (на уровне пользователя), поэтому я бы не назвал это параллельным. Другие отличаются ..

« масштабирование до бесконечности с точки зрения параллелизма ввода / вывода » - это просто экономия с правдой. Они могут получить больше веры, если скажут, что «могут масштабироваться лучше, чем один поток на клиента, при условии, что клиенты не требуют много», хотя тогда они могут чувствовать себя вынужденными добавить «сдувается при большой нагрузке другими асинхронными решениями». которые используют все ядра на уровне пользователя ».

Мартин Джеймс
источник
Может быть вне контекста, но каждая операция обновления (как с помощью команды INCR) несет блокировку? Если имеется 1000 одновременных запросов и одна операция приращения для ключа (на запрос), гарантирует ли это, что переменная увеличивается только в 1000 раз?
Аманда