Comprensión del modelo de reactor de un solo subproceso

Por lo general, deberíamos encontrarnos con una pregunta de entrevista
de Redis ¿Cuál es el modelo de subprocesamiento de Redis?
En pocas palabras, el modelo de reactor de un único subproceso se utiliza internamente. Se utiliza algo llamado un procesador de eventos archivo. Este procesador de eventos del archivo es de un solo subproceso, por lo Redis es también un modelo de un solo subproceso.
Esto es posible. La participación de un cierto conocimiento de la red Programación:
Qué es BIO, NIO, cuál es la diferencia entre los dos
BIO (Bloqueo de E / S): Modo de bloqueo de E / S sincrónico , la lectura y escritura de datos debe estar bloqueada en un hilo esperando su finalización . Cuando el número de conexiones activas no es particularmente alto (menos de 1000 para una sola máquina), este modelo es relativamente bueno, permitiendo que cada conexión se enfoque en su propia E / S y el modelo de programación es simple, sin demasiada consideración del sistema. sobrecarga, limitación actual y otros problemas. El grupo de subprocesos en sí es un embudo natural, que puede almacenar en búfer algunas conexiones o solicitudes que el sistema no puede manejar. Sin embargo, cuando se enfrenta a 100.000 o incluso millones de conexiones, el modelo BIO tradicional es impotente. Por lo tanto, necesitamos un modelo de procesamiento de E / S más eficiente para hacer frente a una mayor concurrencia.
NIO (New I / O): NIO es un modelo de I / O síncrono sin bloqueo . En Java 1.4, se introdujo el marco NIO , correspondiente al paquete java.nio , que proporciona abstracciones como Channel, Selector y Buffer. La N en NIO puede entenderse como no bloqueante, no simplemente como nueva. Admite métodos de operación de E / S basados ​​en canales y orientados al búfer. NIO proporciona dos implementaciones de canal de socket diferentes, SocketChannel y ServerSocketChannel correspondientes a Socket y ServerSocket en el modelo BIO tradicional.Ambos canales admiten modos de bloqueo y no bloqueo. El uso del modo de bloqueo es como el soporte tradicional, relativamente simple, pero el rendimiento y la confiabilidad no son buenos; modo sin bloqueo

Todo lo contrario. Para aplicaciones de baja carga y baja concurrencia, puede usar E / S de bloqueo síncrono para aumentar la tasa de desarrollo y una mejor capacidad de mantenimiento; para aplicaciones de alta carga y alta concurrencia (red), debe usar el modo sin bloqueo de NIO para desarrollar
esto Es una definición copiada, ¿cómo la entiendes?
Después de ver muchos videos, escribí el código yo mismo y hablé sobre mi propio entendimiento.
Primero, déjame hablar sobre BIO, el mecanismo de bloqueo síncrono. Escribí un pequeño código de servidor de demostración
.

public class RedisServer {
    
    
    public static void main(String[] args) throws IOException {
    
    
        ServerSocket serverSocket = new ServerSocket(9090);
        while (true){
    
    
            //阻塞的方法
            Socket socket = serverSocket.accept();
            System.out.println("XXXXX来连接了");
            //在这里是错误的方法,因为我们的BIO不把我们的socket放入线程的话是不能支持并发的
            //因为我们的read方法是会阻塞的,我们另一个客户端进来会在这个地方阻塞掉,是不会回去接收我们的客户端的socket的,所以只能有一个客户端连接
            byte[] bytes = new byte[1024];
            //阻塞的方法   没有消息可读会阻塞
            socket.getInputStream().read(bytes);
            System.out.println("收到客户端的消息" + new String(bytes));
        }
    }
}

Codigo del cliente

public class RedisClient {
    
    
    public static void main(String[] args) throws IOException {
    
    
        Socket socket =  new Socket("127.0.0.1",9090);
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        socket.getOutputStream().write(s.getBytes());
        socket.close();
    }
}

Imagine que un cliente se conecta, no debería haber ningún problema, pero si dos o más clientes se conectan al servidor, habrá un problema, porque cuando el segundo cliente se conecta, el método read () del servidor es El mecanismo de bloqueo síncrono significa que nuestro El método bloqueará este lugar y el segundo cliente no podrá operar.
Esta es también la razón por la que colocamos esta parte del código del servidor en Thread para su ejecución. Las operaciones de un solo subproceso no admiten la concurrencia, pero el problema vuelve a aparecer. Todos sabemos que los subprocesos que ocupan recursos son muy valiosos. Si nuestro It sería Es malo para el servidor crear una gran cantidad de subprocesos (recursos, uso de CPU, etc.) ¿Qué pasa con el uso de grupos de subprocesos? De hecho, puede resolver parte del problema, pero no se puede resolver perfectamente. ¿Qué debo hacer? Es nuestro NIO , que se dedica a manejar problemas de concurrencia de múltiples solicitudes en un solo hilo.

Agrega algo de conocimiento

Dibujar comprensión, comprensión sobre la base de otros, la similitud es aprender de los demás.
Una conexión de solicitud comparte varios sockets.
Inserte la descripción de la imagen aquí
¿Cómo procesa un solo hilo las solicitudes concurrentes?
El paquete NIO proporciona una colección de selectores denominada Selector.
Publiqué parte del código.

        selector = Selector.open();//创建选择器对象
        ssc = ServerSocketChannel.open();//打开服务端socket
        InetSocketAddress addr = new InetSocketAddress(port);
        ssc.socket().bind(addr);//在我们的ServerSockerChanel绑定端口
        ssc.configureBlocking(false);//设置ServerSockerChanel为非阻塞
        //
        SelectionKey sk = ssc.register(selector,SelectionKey.OP_ACCEPT);//
        //给定key一个附加的Acceptor对象,我们可以通过这个来判断是什么事件
        sk.attach(new Acceptor(selector,ssc));

Otra parte del código es así. En cuanto a qué negocio no nos importa, acabo de llegar a comprender esta idea.

            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> it = selectionKeys.iterator();
            //遍历已经发生的事件
            while (it.hasNext()){
    
    
                SelectionKey selectionKey = it.next();
                //根据事件的Key去调度
                dispatch(selectionKey);
                it.remove();
            }

Diagrama de flujo Inserte la descripción de la imagen aquí
Es decir, en el caso de un solo hilo, usamos un conjunto de selectores para almacenar nuestro socket, aquí también se adjunta un objeto Acceptor, el
proceso es:
si nos conectamos por primera vez, aceptaremos nuestra solicitud Registrarse a esta colección, adjunte información sobre él y, a continuación, recorra nuestra colección de teclas de selección en este momento para ver qué intereses están almacenados en ella. Si se acepta, llamaré a su método de ejecución. Si se lee, llamo a la ejecución método de lectura, y varias solicitudes al mismo tiempo, tanto enlaces como solicitudes de lectura, luego las pongo en mis selectKeys juntas, sondeando una por una operación, una por una eliminación, esto es lo que entiendo NIO Idea general
Entonces entendamos el modelo de subprocesamiento de redis. Aquí publico
el blog de un hermano mayor. Creo que el modelo de redis que escribió es bueno.

Supongo que te gusta

Origin blog.csdn.net/qq_22155255/article/details/115262800
Recomendado
Clasificación