关于nodejs下redis/mysql需不须要链接池的问题

链接池的做用主要是较少每次临时创建链接所带来的开销。初步一看,nodejs运行单线程上,它不能同时使用多个链接,乍一看是不须要链接池的。可是这只是咱们初步下意识的感受,下面咱们详细分析来看看这个结论对是不对。 node

 

先从简单的redis开始。
redis服务器也是运行在单线程上的。俩都是单线程,看起来更加坚决不须要链接池的结论了。
从详细的图像来看看nodejs 链接 redis用链接池有没有意义。
 
上图中,nodejs共有俩链接,分别发送查询请求到redis服务器上。由于redis是单线程做业,无论两个查询任务是由一个链接发来仍是多个链接发来,也无论任务是串行一前一后前后发送到服务器,仍是并行的同时发送到服务器上,redis都将他们一个个按顺序执行,并经过当前链接返回给客户端(这里是nodejs)。nodejs接受到redis的返回后,也管不了并行不并行,都得等他nodejs的主线程空闲的时候才能来一个个处理服务器返回的数据。
 
因此单从上面结论来看,nodejs + redis只须要公用一个链接就能够了,因此是不须要用链接池的。
 
再来看看nodejs + mysql下的状况
 
不一样的是mysql不是单线程服务的,也就是它能够并行处理多个查询请求。
如上图所示,mysql会为每一个链接建立一个单独的线程来查询。不一样于redis数据基本都在内存中,由于mysql会有大量的读取磁盘的IO操做,因此多个线程一块儿工做会比一个个查询要快。
 
可是nodejs又是单线程的,它能不能同时发送多个请求到mysql服务器上呢?
这里要理解nodejs的运做,虽然nodejs是一个主线程,可是它调用的IO指令等是经过另外的线程去作的,IO指令完成后就给主线程一个小任务片,也就是回调函数了。
这里有个很关键的点就是,nodejs主线程一个,可是IO线程会有多个。
所以若是用nodejs + mysql只用单个链接的话那么就利用不到mysql能同时服务多个查询的优点了。应该使用相似下图的运做方式,nodejs 使用多个链接来链接mysql。多链接是须要链接池的,有链接池就避免了每次链接都要去建立销毁的消耗了。
 
因此咱们第一步的感受认为Nodejs是单线程而不是须要链接池是错误的,使用不使用链接池,不光看客户端,还要看数据库服务器等。要全盘理解整个系统的运做模式才能下结论。了解服务器的运做模式,有没有阻塞操做,是不是多线程等。我想redis设计成单线程主要缘由在于它的数据基本都在内存中,查询数据过程总不会产生阻塞过程,cpu也不会处于空闲状态。
 

全局链接断开重连问题

到这里还没完。综上面的分析,nodejs + mysql用线程池是没什么问题的。nodejs + redis只用单个链接就够。不过也仍是有人建议须要链接池。为了说明问题得从代码着手。咱们使用node-redis这个包来作例子。
 
例如新建了一个db.js
var redis = require("redis"), client = redis.createClient(6379, "127.0.0.1"); module.exports = client;

上面的链接会在程序启动载入完后就链接上了。使用它的时候引入它就可使用全局惟一的链接。 mysql

复制代码
var db = require("db.js"); exports.add = function(req, res, next) { db.get("keyName", function() { res.send("ok");  }); }
复制代码
这里因而有这样的问题存在。
但此处全局只有一个链接,而且这个链接是程序启动的时候建立的。它不一样于链接池中的链接那样运行时候动态建立。若是某个时候惟一的链接断掉了,程序又不会动态去建立链接,岂不是须要从新启动服务器才行。
 
看是来挺可怕,但好在这个问题是不存在的。由于redis的客户端会自动从新链接,因此不须要从新启动服务器。
可是由于链接断开那一小段时间,应用服务器不能正常对外服务,可是链接自动重连是须要必定的时间间隔的。例如一秒以后,因此这一秒以内系统是处在不能服务状态。
 
也正是基于上面这样的缘由,因而就有链接redis使用链接池的作法。若是使用链接池来管理,当链接不可用的时候当即手动去建立新链接。和自动重连相比,一个是手动当即重连,一个是等到必定间隔重连。相对来讲手动重连的时间更短,也就是说系统那1秒中不能服务的状态或许能够缩短成0.5秒。因而就有了使用链接池管理redis链接的作法。严格来讲这个不能算是链接池,而是一个链接管理模块。 
 
到这里最后的结论nodejs + mysql使用链接池更好, nodejs + redis可使用也能够不用。