Redis tiene un solo subproceso, entonces, ¿cómo funciona la E / S concurrente?

170

Intentando comprender algunos conceptos básicos de Redis, me encontré con una publicación de blog interesante .

El autor declara:

Redis tiene un solo subproceso con epoll / kqueue y escala indefinidamente en términos de concurrencia de E / S.

Seguramente no entiendo todo el tema del enhebrado, porque esta declaración me resulta desconcertante. Si un programa tiene un solo subproceso, ¿cómo hace algo al mismo tiempo? ¿Por qué es tan bueno que las operaciones de Redis sean atómicas, si el servidor tiene un solo subproceso de todos modos?

¿Alguien podría arrojar algo de luz sobre el tema?

Przemysław Pietrzkiewicz
fuente

Respuestas:

362

Bueno, depende de cómo se defina la concurrencia.

En el software del lado del servidor, la concurrencia y el paralelismo a menudo se consideran conceptos diferentes. En un servidor, admitir E / S concurrentes significa que el servidor puede servir a varios clientes mediante la ejecución de varios flujos correspondientes a esos clientes con una sola unidad de cálculo. En este contexto, el paralelismo significaría que el servidor puede realizar varias cosas al mismo tiempo (con múltiples unidades de cálculo), lo cual es diferente.

Por ejemplo, un cantinero puede cuidar a varios clientes mientras que solo puede preparar una bebida a la vez. Entonces él puede proporcionar concurrencia sin paralelismo.

Esta pregunta se ha debatido aquí: ¿Cuál es la diferencia entre concurrencia y paralelismo?

Vea también esta presentación de Rob Pike.

Un programa de un solo subproceso definitivamente puede proporcionar concurrencia en el nivel de E / S mediante el uso de un mecanismo de multiplexación (des) de E / S y un bucle de eventos (que es lo que hace Redis).

El paralelismo tiene un costo: con los múltiples sockets / múltiples núcleos que puede encontrar en el hardware moderno, la sincronización entre hilos es extremadamente costosa. Por otro lado, el cuello de botella de un motor de almacenamiento eficiente como Redis es muy a menudo la red, mucho antes que la CPU. Por lo tanto, los bucles de eventos aislados (que no requieren sincronización) se consideran un buen diseño para construir servidores eficientes y escalables.

El hecho de que las operaciones de Redis sean atómicas es simplemente una consecuencia del bucle de eventos de un solo subproceso. El punto interesante es que la atomicidad se proporciona sin costo adicional (no requiere sincronización). El usuario puede explotarlo para implementar un bloqueo optimista y otros patrones sin pagar la sobrecarga de sincronización.

Didier Spezia
fuente
135
Buena analogía de barman :)
Sergio Tulentsev
3
v4 es un cambio de juego en este sentido - vea mi respuesta en stackoverflow.com/a/45374864/3160475 :)
Itamar Haber
1
lo único que realmente no me gusta de la respuesta y la comparación es que parece que la concurrencia no funciona en paralelo y ciertamente lo hace, ya que puedo probar esto con la ejecución de tareas asíncronas y hacer el trabajo que finalmente es considerado como en paralelo. el paralelismo en el contexto de ese artículo se refiere a la naturaleza multinúcleo de poder ejecutarse en múltiples hilos. Es decir, por qué se refieren a que es seguro.
Christian Matthew
¿Sigue siendo válido en 2020?
Roberto Manfreda
21

OK, Redis tiene un solo subproceso a nivel de usuario, OTOH, todas las E / S asíncronas son compatibles con grupos de subprocesos del núcleo y / o controladores de nivel dividido.

' Concurrente ', para algunos, incluye la distribución de eventos de red a máquinas de estado de socket. Es de un solo subproceso, se ejecuta en un núcleo (a nivel de usuario), por lo que no me referiría a esto como concurrente. Otros difieren ..

' escalar indefinidamente en términos de concurrencia de E / S ' es solo ser económico con la verdad. Pueden creer más si dicen "pueden escalar mejor que un subproceso por cliente, siempre que los clientes no pidan mucho", aunque entonces pueden sentirse obligados a agregar "impresionado por la carga pesada de otras soluciones asíncronas". que usan todos los núcleos a nivel de usuario '.

Martin James
fuente
Puede estar fuera de contexto, pero ¿cada operación de actualización (como por comando INCR) lleva un bloqueo? Si hay 1000 solicitudes concurrentes y una operación de incremento en una clave (por solicitud), ¿eso asegura que la variable se incremente solo 1000 veces?
Amanda