Nodejs 连接 Redis数据库实例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nodejs 连接 Redis数据库实例相关的知识,希望对你有一定的参考价值。

参考技术A 报错:Node连接Redis报错 “ClientClosedError: The client is closed”

查询资料才发现:Node Redis版本V4之后,连接语法变了。

Starting from v4 of node-redis library, you need to call client.connect() after initializing a client. See this migration guide.

新语法:

const redis = require('redis');

const client = redis.createClient( socket: port: 6379 );

client.connect();

client.on('connect', () =>

    console.log('connected');

);

You might also want to consider running the client connect method with await in an asynchronous function. So you don't have to worry about event listeners.

const redis = require('redis');

(async () =>

  try

    const client = redis.createClient( socket: port: 6379 );

    await client.connect();

    console.log('connected');

  catch (err)

    console.error(err)

 

)()

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[Example]:
const redis = require("redis");

(async () =>

  try

    const client = redis.createClient(

      socket: port: 6379 ,

      legacyMode: true,

    );

    await client.connect();

    console.log("connected");

    await client.v4.set("key4", "value2",

      NX: true,

    );

    client.set("key3", "value3", "NX", (err, reply) => );

    await client.get("key4", function (err, v)

      console.log("redis get hello err,v", err, v);

    );

    client.set("student1", "Laylaa1", function (err, reply)

      if (err)

        console.log(err);

        callback(err, null);

        return;

     

      console.log(reply);

    );

  catch (err)

    console.error(err);

 

)();

nodejs + redis/mysql 连接池问题

连接池是必须的么?

连接池的作用主要是较少每次临时建立连接所带来的开销。初步一看,nodejs运行单线程上,它不能同时使用多个连接,乍一看是不需要连接池的。但是这只是我们初步下意识的感觉,下面我们详细分析来看看这个结论对是不对。

先从简单的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 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可以使用也可以不用。

以上是关于Nodejs 连接 Redis数据库实例的主要内容,如果未能解决你的问题,请参考以下文章

如何连接nodejs sequelize aws rds mysql数据库和ec2实例

Node.js如何使用MySQL的连接池实例

阿里云-Redis-Help-连接实例-Redis客户端连接:Jedis客户端

nodejs+mysql入门实例(改)

10_Redis_多数据库

Nodejs后台管理员登录实例