Node全栈--数据库

758 阅读3分钟

 NoSQL数据库

NoSQL(Not Only SQL)简介

  1. 非关系型数据库,对象实体关联少, 如MongoDB,支持复杂度相对高的数据结构, 能够将相关联的数据以文档的方式接入,从而减少数据之间的关联操作
  2. 通过数据的分布式存储大幅地提供存储性能
  3. 提供了强大的数据可用性,在应用中,能快速反馈信息给使用者
  4. 事务处理跟一致性弱,如果对性能有要求, 只能做到数据最终一致

一个项目中,可以同时有NoSQL数据库和RDB数据库,将数据拆开设计

  • NoSQL分类

image.png

  • 什么是MongoDB及特点

  1. 官网: docs.mongodb.com
  2. 由C++语言编写,基于分布式文件存储的开源NoSQL数据库系统
  3. 将数据存储为BSON文档(BSON规范),数据结构由键值对组成 key => value, 字段值可以包含其他文档,数组及文档数据, mongoDB 可以想象为一个超级大对象

image.png 注: field对应关系型数据库中的Column, 集合Collection对应关系型数据库中的Table

       4. 查询功能非常强大, 类似于面向对象的程序语言

  • 在Node.js中操作MongoDB

  • 什么是Redis 

官网:redis.io/

        基于ANSI C编写的开源的,遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库,并提供多种语言的 API

  • Redis 安装(macOS)

           以macOS为例,其他系统参考:www.runoob.com/redis/redis…

  1.  安装homebrew(已安装忽略此步骤)

    /bin/bash -c "$(curl -fsSL https://cdn.jsdelivr.net/gh/ineo6/homebrew-install/install.sh)"
    
  2. 安装redis

    brew install redis
    
  3. 启动redis, redis会默认占用6379端口

        redis-server //  或者后台启动 redis-server --daemonize yes
    

    使用 ps -ef | grep -i redis 查看redis是否启动

  4. 停止redis, 强制终止Redis进程可能导致数据丢失,所以,应该向Redis发送shutdown命令

    redis-cli shutdown
    

    注: Redis可以妥善处理SIGTERM信号,所以使用kill Redis进程的PID也可以正常结束Redis

  5. Redis持久化:默认为RDB方式, 可通过conf配置文件appendonly yes 改为AOF方式

  • Redis图形管理软件RDM

    下载地址: rdm.dev/

  • 在Node.js中操作Redis 

Nodejs中可以操作Redis的软件包如下: redis.io/clients#nod… 以 ioredis(github.com/luin/ioredi…) 为例(ioredis使用较为广泛,如阿里,公司B2B商城等使用的是ioredis, 并且支持原生Promise)

  1. 基本使用

const Redis = require("ioredis");
const redis = new Redis(); // uses defaults unless given configuration object

// ioredis supports all Redis commands:
redis.set("foo", "bar"); // returns promise which resolves to string, "OK"

// the format is: redis[SOME_REDIS_COMMAND_IN_LOWERCASE](ARGUMENTS_ARE_JOINED_INTO_COMMAND_STRING)
// the js: ` redis.set("mykey", "Hello") ` is equivalent to the cli: ` redis> SET mykey "Hello" `

// ioredis supports the node.js callback style
redis.get("foo", function (err, result) {
  if (err) {
    console.error(err);
  } else {
    console.log(result); // Promise resolves to "bar"
  }
});

// Or ioredis returns a promise if the last argument isn't a function
redis.get("foo").then(function (result) {
  console.log(result); // Prints "bar"
});

// Most responses are strings, or arrays of strings
redis.zadd("sortedSet", 1, "one", 2, "dos", 4, "quatro", 3, "three");
redis.zrange("sortedSet", 0, 2, "WITHSCORES").then((res) => console.log(res)); // Promise resolves to ["one", "1", "dos", "2", "three", "3"] as if the command was ` redis> ZRANGE sortedSet 0 2 WITHSCORES `

// All arguments are passed directly to the redis server:
redis.set("key", 100, "EX", 10);

2. 管道(Pipelining)redis.io/topics/pipe…

const pipeline = redis.pipeline();
pipeline.set("foo", "bar");
pipeline.del("cc");
pipeline.exec((err, results) => {
  // `err` is always null, and `results` is an array of responses
  // corresponding to the sequence of queued commands.
  // Each response follows the format `[err, result]`.
});

// You can even chain the commands:
redis
  .pipeline()
  .set("foo", "bar")
  .del("cc")
  .exec((err, results) => {});

// `exec` also returns a Promise:
const promise = redis.pipeline().set("foo", "bar").get("foo").exec();
promise.then((result) => {
  // result === [[null, 'OK'], [null, 'bar']]
});

3. 事务

redis
  .multi()
  .set("foo", "bar")
  .get("foo")
  .exec((err, results) => {
    // results === [[null, 'OK'], [null, 'bar']]
  });

事务中默认带管道, 如果不需要管道(不建议,管道能提高效率),需要将{pipeline: false} 传递给multi, 每个命令将立即发送到Redis,而无需等待exec调用

4. 错误信息

  启用showFriendlyErrorStack,优化错误堆栈

image.png