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()) { // 可写 } } }