O Redis é de thread único; então, como ele faz E / S simultânea?

170

Tentando entender alguns conceitos básicos do Redis, me deparei com um post interessante no blog .

O autor declara:

O Redis possui um encadeamento único com epoll / kqueue e é dimensionado indefinidamente em termos de simultaneidade de E / S.

Eu certamente não entendi direito a coisa toda, porque acho essa afirmação intrigante. Se um programa é de thread único, como ele faz algo simultaneamente? Por que é tão bom que as operações Redis sejam atômicas, se o servidor for de thread único de qualquer maneira?

Alguém poderia esclarecer um pouco sobre o assunto?

Przemysław Pietrzkiewicz
fonte

Respostas:

361

Bem, isso depende de como você define a simultaneidade.

No software do lado do servidor, simultaneidade e paralelismo são frequentemente considerados como conceitos diferentes. Em um servidor, suportar E / Ss simultâneas significa que o servidor pode atender a vários clientes executando vários fluxos correspondentes a esses clientes com apenas uma unidade de computação. Nesse contexto, paralelismo significaria que o servidor é capaz de executar várias coisas ao mesmo tempo (com várias unidades de computação), o que é diferente.

Por exemplo, um barman é capaz de cuidar de vários clientes, enquanto ele só pode preparar uma bebida de cada vez. Para que ele possa fornecer simultaneidade sem paralelismo.

Esta questão foi debatida aqui: Qual é a diferença entre simultaneidade e paralelismo?

Veja também esta apresentação de Rob Pike.

Um programa de thread único pode definitivamente fornecer simultaneidade no nível de E / S usando um mecanismo de multiplexação de E / S (des) e um loop de eventos (que é o que Redis faz).

O paralelismo tem um custo: com os vários soquetes / múltiplos núcleos que você encontra no hardware moderno, a sincronização entre os segmentos é extremamente cara. Por outro lado, o gargalo de um mecanismo de armazenamento eficiente como o Redis geralmente é a rede, muito antes da CPU. Os loops de eventos isolados (que não requerem sincronização) são, portanto, vistos como um bom design para criar servidores eficientes e escaláveis.

O fato de as operações Redis serem atômicas é simplesmente uma consequência do loop de eventos de thread único. O ponto interessante é que a atomicidade é fornecida sem custo adicional (não requer sincronização). Ele pode ser explorado pelo usuário para implementar o bloqueio otimista e outros padrões sem pagar pela sobrecarga de sincronização.

Didier Spezia
fonte
135
Analogia barman agradável :)
Sergio Tulentsev
3
v4 é uma virada de jogo a este respeito - ver a minha resposta em stackoverflow.com/a/45374864/3160475 :)
Itamar Haber
1
a única coisa que eu realmente não gosto na resposta e na comparação é que ela faz parecer que a simultaneidade não funciona em paralelo e certamente funciona, pois posso testá-la com a execução de tarefas assíncronas e com o trabalho finalizado. considerado em paralelo. o paralelismo no contexto desse artigo refere-se à natureza multicore de poder executar em threads múltiplos. Ou seja, por que se referem a ser thread-safe.
Christian Matthew
Ainda válido em 2020?
Roberto Manfreda 20/02
21

OK, o Redis possui um encadeamento único no nível do usuário, OTOH, todas as E / S assíncronas são suportadas por conjuntos de encadeamentos do kernel e / ou drivers de nível dividido.

' Concorrente ', para alguns, inclui a distribuição de eventos de rede para soquete de máquinas de estado. É de thread único, é executado em um núcleo (no nível do usuário), portanto, eu não me referiria a isso como simultâneo. Outros diferem ..

' escala indefinidamente em termos de simultaneidade de E / S ' está apenas sendo econômico com a verdade. Eles podem ter mais crença se disserem que 'podem escalar melhor do que um thread por cliente, desde que os clientes não exijam muito', embora possam se sentir obrigados a adicionar 'desdobrado em cargas pesadas por outras soluções assíncronas que usam todos os núcleos no nível do usuário '.

Martin James
fonte
Pode estar fora de contexto, mas cada operação de atualização (como no comando INCR) carrega um bloqueio? Se houver 1000 solicitações simultâneas e uma operação de incremento em uma chave (por solicitação), isso garante que a variável seja incrementada apenas 1000 vezes?
Amanda