Modelo de E/S de Redis

Todas nuestras aplicaciones están implementadas en el sistema Linux. El sistema Linux también es una aplicación y es un software de sistema operativo basado en hardware de computadora. Cuando recibimos una transmisión de red, la tarjeta de red del hardware de la computadora escribirá el flujo de bytes leído de la red en la memoria intermedia de Linux, y luego el espacio de usuario llamará a la interfaz expuesta de Linux para transferir los datos en la memoria intermedia de Linux. Leer en el espacio del usuario. Esta operación de lectura es una IO. Lo mismo ocurre con la escritura.

Los diferentes sistemas operativos tienen diferentes modelos de IO. A continuación se muestran algunos modelos IO de sistemas Linux.

Esto se hace para proteger el sistema operativo Linux y evitar que aplicaciones externas o humanos operen directamente el sistema del kernel.

El estado de un hilo cuando se ejecuta en el espacio de usuario se llama estado de usuario.

El estado de un hilo cuando se ejecuta en el espacio del kernel se llama estado del kernel.

Cuello de botella en el rendimiento de IO:

A. Cambio entre el modo de usuario y el modo kernel (copia de datos)

Bloqueo de espera de subprocesos de lectura y escritura

p>

El modelo IO de Linux está optimizado para estos dos puntos.

Cuando el subproceso de la aplicación del usuario llama a la función recvfrom del sistema operativo Linux para leer datos, si no hay datos en la memoria intermedia del kernel, el subproceso del usuario se bloqueará y esperará hasta que haya datos en la memoria del kernel. memoria intermedia y luego el kernel. Los datos de la memoria intermedia se copian a la memoria de la aplicación del usuario.

Similar a hacer cola para comprar bollos al vapor, no hay bollos al vapor en este momento, pero no sabes si hay bollos al vapor. Si no hay bollos al vapor, puedes esperar allí y no hacer nada. Cuando los bollos estén horneados, recógelos y guárdalos en tu bolsillo.

Problema:

Cuando se bloquea un hilo, todos los hilos posteriores se bloquearán. Incluso si los datos de lectura y escritura posteriores están listos, no se pueden leer ni escribir.

Cuando el subproceso de la aplicación del usuario llama a la función recvfrom del sistema operativo Linux para leer datos, si no hay datos en la memoria intermedia del kernel, el subproceso del usuario obtendrá directamente el resultado (sin datos) sin esperar. , por lo que iniciará otra llamada a la función recvfrom hasta que haya datos en la memoria intermedia del kernel y luego copiará los datos en la memoria intermedia del kernel a la memoria de la aplicación del usuario.

Es similar a cuando haces cola para comprar bollos al vapor y el jefe directamente te dice que no hay bollos al vapor. Ya sabes el resultado. Le preguntas al jefe una y otra vez si tiene bollos al vapor. No puedes guardar los bollos en tu bolsillo hasta que el jefe te lo diga.

Problema:

Si no hay datos, el subproceso llamará a la función recvfrom en un bucle infinito, utilizando con frecuencia recursos de la CPU, lo que provocará un desperdicio de recursos de la CPU.

El kernel) utiliza descriptores de archivos para acceder a los archivos. El descriptor de archivo es un número entero no negativo. Al abrir un archivo existente o crear un archivo nuevo, el kernel devuelve un descriptor de archivo. Leer y escribir archivos también requiere el uso de descriptores de archivos para especificar los archivos que se leerán y escribirán. Los archivos incluyen archivos de audio, archivos normales, dispositivos de hardware, etc. , también incluye web sockets.

La multiplexación IO consiste en utilizar un solo subproceso para monitorear más descriptores de archivos FD. Cuando un descriptor de archivo FD es legible y escribible, recibe una notificación para evitar esperas no válidas y aprovechar al máximo los recursos de la CPU.

El hilo de la aplicación del usuario llama a la función de selección para monitorear múltiples descriptores de archivos FD. Si no hay datos, todavía hay que esperar. Si hay un archivo FD listo, significa que hay datos, luego lea los datos del archivo listo FD correspondiente. En este momento, el kernel copiará el archivo FD configurado en la memoria del usuario, luego recorrerá el conjunto FD para encontrar el FD que pueda leer los datos y luego leerlo. Después de leer, copia el FD configurado en la memoria del kernel.

Similar a hacer cola para pedir en un restaurante. En este momento hay un camarero vigilando la cocina a través de una tablet. Sólo tienes que preguntarle al camarero si hay algo para comer. Si no, igual tendrás que esperar, pero si lo hace, el camarero sabrá mediante el seguimiento que hay comida y te permitirá pedirla.

De hecho, el principio del modo de sondeo es similar al del modo de selección.

La diferencia es que se agrega un evento de evento en la parte inferior del modo de sondeo, que se divide en eventos de lectura, eventos de escritura, eventos de excepción, etc.

Proceso:

A. Primero agregue el evento a monitorear, ya sea un evento de lectura o un evento de escritura, pueden ser múltiples eventos.

b. Convierta el evento monitoreado FD en una lista vinculada y guárdelo en el búfer del kernel.

c. El búfer del kernel copia la lista vinculada de FD de eventos al búfer del usuario y devuelve el número de FD listos.

d. Determine el número de FD listos en la caché del usuario. Si es mayor que 0, inicie la lista vinculada de FD de eventos de conveniencia.

Problemas con el modo de sondeo:

A. Debe copiar toda la lista enlazada de FD desde el espacio del usuario al espacio del kernel y luego copiarla al espacio del usuario después del sondeo.

B.poll no puede saber qué evento FD específico es y necesita promocionar todo el evento FD (lista vinculada).

Modo de selección de contraste

Debido a que se utiliza una lista vinculada, la cantidad de eventos puede ser teóricamente incontable, pero a medida que aumenta la cantidad de eventos, el rendimiento transversal de la lista vinculada disminuirá . Cuando el evento no esté listo, todavía hay que esperar.

El modo Epoll se mejora en función del modo de encuesta. Primero, cambie la lista vinculada FD que almacena eventos a un árbol rojo-negro (teóricamente no hay límite superior El rendimiento transversal del árbol rojo-negro es estable). En segundo lugar, copie el evento listo específico por separado y luego cópielo en el búfer del usuario. El búfer del usuario obtiene el evento listo sin mejorar el rendimiento transversal nuevamente.

Proceso:

a. Primero, registre los eventos de monitoreo

B. Instale todos los FD en el árbol rojo-negro.

c. Cuando el FD esté listo, llame a la función de devolución de llamada para copiar el FD correspondiente a la lista vinculada.

d. Copie la lista vinculada del búfer del kernel al búfer del usuario y devuelva el tamaño de la lista vinculada n

E El hilo del usuario determina directamente el tamaño de n. no es 0, los datos de la lista vinculada se pueden leer directamente (todo listo FD).

Cuando el hilo de la aplicación del usuario llama a la función sigaction del sistema operativo Linux, regresa directamente y luego el hilo hace otras cosas. Cuando llegan los datos, el espacio del kernel envía una señal al espacio del usuario. En este momento, el espacio del usuario llamará a la función recvfrom para copiar los datos del búfer del espacio del kernel al búfer del espacio del usuario y procesar los datos.

Es similar a cuando pides comida, el camarero te dará un número y luego, cuando tu comida esté lista, el camarero llamará a tu número y luego recogerás la comida.

Problema:

Cuando se llaman demasiados subprocesos, el semáforo correspondiente aumentará y la función SIGIO no se puede procesar a tiempo, lo que provoca que la cola que almacena la señal se desborde y la cola; espacio del kernel y usuario El espacio interactúa frecuentemente con semáforos y tiene un rendimiento deficiente.

En términos de rendimiento, también es bueno, pero en el desarrollo real, necesita controlar la concurrencia de subprocesos, por lo que será muy problemático de implementar, por lo que rara vez se usa.

Entre los tres métodos de reutilización de IO, epoll tiene el mejor efecto. Se solucionó un problema en los modos de selección y sondeo.

Redis es un modelo IO en modo epoll.