面试官:redis和memcached有什么区别。我:redis是单线程的,memcaced是多线程的。好,那么redis真的是单线程的吗?
网络IO、线程模型
localhost bin]# ps -T -p 3081
PID SPID TTY TIME CMD
3081 3081 ? 00:00:00 redis-server
3081 3088 ? 00:00:00 redis-server
3081 3089 ? 00:00:00 redis-server
3081 3090 ? 00:00:00 redis-server
纳尼?说好的单线程呢?
从网络IO模型讲起
同步模型(synchronous IO)
阻塞IO(bloking IO)
非阻塞IO(non-blocking IO)
多路复用IO(multiplexing IO)
信号驱动式IO(signal-driven IO)
大家可以了解一下Reactor模式(单线程、多线程),其实Reactor模式中就是利用epoll或者select多路复用函数库来实现。
异步IO(asynchronous IO)
Proactor模式利用异步IO来实现,区别于Reactor,就读事件这个点而言,在于Reactor执行实际的读取操作,而Proactor是操作系统调用内核线程完成读取操作,并将读取的内容放入用户传递过来的缓存区中。
有没有想起Spring中的IOC依赖反转,将对象生命周期控制权讲给Spring容器,那这里我把它形容成读写反转,真正的读写操作交给操作系统。
我们的redis用的是哪种网络IO模型呢,是不是经常听到多路复用,对,没错,redis用的就多路复用的网络模型(I/O多路复用程序的所有功能是通过包装select、epoll、evport和kqueue这些I/O多路复用函数库来实现的),也是我们常提到nio网络模型。
好,的确有点抽象,我们来看一下java里面如何实现的这个模型的。
服务端逻辑代码
public class MultiplexerTimeServerHandler implements Runnable {
private Selector selector = null;
private ServerSocketChannel servChannel = null;
private int port;
private boolean stop;
/**
* 初始化多路复用器,绑定监听端口
*
* @param port
*/
public MultiplexerTimeServerHandler(int port) {
try {
selector = Selector.open();
servChannel = ServerSocketChannel.open();
//非阻塞
servChannel.configureBlocking(false);
servChannel.socket().bind(new InetSocketAddress(port), 1024);
//在通道上注册selector,感兴趣事件是OP_ACCEPT
servChannel.register(selector, SelectionKey.OP_ACCEPT);
System<