吴庆龙的技术轮子

学习的目的是输出。

导航

Redis单线程模型

1、单线程模型概述

Redis 使用单线程模型来处理各种 socket 事件,所以说 Redis 是单线程的,使用单线程轮训所有 socket 连接,监听所有 socket 发送过的命令,然后对齐进行响应,如果其中一个 socket 的命令执行时间过长,则会导致后续的客户端命令产生堵塞。

2、为什么采用单线程模型还这么快?

  • 纯内存操作。
  • 单线程可以避免上下文切换,不用考虑锁的问题。
  • 使用 IO多路复用模型,非堵塞IO。多路是指多个网络连接,复用是指使用一个线程进行处理。

3、单线程模型代码

public class NIOServer implements Runnable {
 
    private final Selector selector = Selector.open();
    private final ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
 
    public NIOServer() throws IOException {
        serverSocketChannel.socket().bind(new InetSocketAddress(9999));
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    }
 
    @Override
    public void run() {
        while (!Thread.interrupted()) {
            try {
                if (selector.select() <= 0) {
                    continue;
                }
 
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
 
                    // 分发事件
                    dispatchEvent(selectionKey);
 
                    iterator.remove();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
    /**
     * 分发事件处理
     */
    private void dispatchEvent(SelectionKey selectionKey) throws IOException {
        if (selectionKey.isAcceptable()) {
            // 新连接注册
            SocketChannel socketChannel = serverSocketChannel.accept();
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ);
        } else if (selectionKey.isReadable()) {
            // 可读
        } else if (selectionKey.isWritable()) {
            // 可写
        }
    }
} 

 

posted on 2021-04-17 14:32  蜗牛大师  阅读(91)  评论(0编辑  收藏  举报