Nodejs+mySQL和Redis和MongoDB的数据库互联互通

blockchain

Nodejs开发环境的搭建

  • 简单的说 Node.js 就是运行在服务端的 JavaScript。
  • V8引擎执行Javascript的速度非常快,性能非常好。 [1] Node.js是一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行数据密集型的实时应用。

应用方向

  1. 大型高流量网站都采用Node.JS进行开发,
  2. 开发一些快速移动Web框架,
  3. 应用程序监控、媒体流、远程控制、桌面和移动应用等等[2]

以上资料均来自百度百科


下载:Node.js 中文网

使用 node -v 命令来查看当前的 Node 版本,出现以下情况就安装成功

image1.png

Node.js文档 有Nodejs自带的一些模块。
如果需要其他的模块,只需

npm install jquery

引入下载的模块

var res = require("http.js");

引入自写的模块

var res = require("./foo.js");

更多操作和说明可参见 https://www.runoob.com/nodejs/nodejs-callback.html


Node.js 与MySQL互联互通

MySQL操作,就不多讲,更多教程可参见 http://www.runoob.com/mysql/mysql-tutorial.html

MySQL不是nodejs自带的模块,需下载

npm install mysql

连接数据库

var mysql = require('mysql');
var connection = mysql.createConnection({ 
    host : 'localhost',  //主机地址 (默认:localhost)
    user : 'root',  //用户名
    password : '123456',  //密码
    database : 'test'  //数据库名
});
connection.connect();
connection.query('SELECT * FROM login_table', function (err, result) {
  
});
connection.end();

使用MySQL的连接池:

var pool = mysql.createPool({
    host : 'hostName', 
    user : 'username',
    password: 'password'
});
var  sql = 'SELECT * FROM websites';
pool.getConnection(function(err, connection){
  connection.query(sql,  function(err, rows){
  
  });
  connection.release();
});

数据库操作( CURD ):增、删、改、查对数据库进行操作。

//查
var  sql = 'SELECT * FROM websites';
pool.getConnection(function(err, connection){
  connection.query(sql,  function(err, rows){
  
  });
  connection.release();
});
//增
var  addSql = 'INSERT INTO websites(Id,name,url,alexa,country) VALUES(0,?,?,?,?)';
var  addSqlParams = ['菜鸟工具', 'https://c.runoob.com','23453', 'CN'];
pool.getConnection(function(err, connection){
  connection.query(addSql,addSqlParams,function(err, rows){
  
  });
  connection.release();
});
//改
var modSql = 'UPDATE websites SET name = ?,url = ? WHERE Id = ?';
var modSqlParams = ['菜鸟移动站', 'https://m.runoob.com',6];
pool.getConnection(function(err, connection){
  connection.query(modSql,modSqlParams,function(err, rows){

  });
  connection.release();
});
//删
var delSql = 'DELETE FROM websites where id=6';
pool.getConnection(function(err, connection){
  connection.query(delSql,function(err, rows){
    
  });
  connection.release();
});

更多操作和说明可参见: http://www.runoob.com/nodejs/nodejs-mysql.html
可视化工具:Navicat for MySQL

demo案例 - 使用MySQL数据库的登录注册系统

st=>start: 开始
e1=>end: 进入页面
op1=>operation: 登录
op2=>operation: 登录成功
op3=>operation: 登录失败
op4=>operation: 注册
op5=>operation: 注册成功
op6=>operation: 注册失败
cond1=>condition: 数据库是否存在该用户
cond2=>condition: 数据库是否存在该用户
st->op1->cond1
cond1(yes)->op2->e1
cond1(no)->op3->op4->cond2->cond2(no)->op5
cond2(yes)->op6->op4

node.js与mongodb互联互通

  • MongoDB 是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
  • MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。 [3]

以上资料均来自百度百科

下载地址: https://www.mongodb.com/download-center#community

MongoDB服务的配置

  • 启动mongodb服务之前需要必须创建数据库文件的存放文件夹,否则命令不会自动创建,而且不能启动成功。
  • 创建数据库文件的存放位置,比如d:/data/db;
  • 在d:\data下新建文件夹log(存放日志文件)并且新建文件mongodb.log;
  • 在d:\data新建文件mongo.config;
  • 用记事本打开mongo.config输入:
dbpath=D:\data\db
logpath=D:\data\log\mongodb.log  

在MongoBD的bin目录下,(也可以配置环境变量)
输入如下的命令启动mongodb服务:

mongod.exe --dbpath d:\data\db

如图打开服务,出现以下情况则配置成功

image2 (2).png

更多操作和说明可参见:
http://www.runoob.com/mongodb/mongodb-tutorial.html

创建连接、集合

var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, function (err, db) {
    if (err) throw err;
    console.log('数据库已创建');
    var dbase = db.db("runoob");
    dbase.createCollection('site', function (err, res) {
        if (err) throw err;
        console.log("创建集合!");
        db.close();
    });
});

数据库操作( CURD )

//插入一条数据
//插入多条数据可以使用 insertMany():
 var myobj = { name: "菜鸟教程", url: "www.runoob" };
  dbase.collection("site").insertOne(myobj, function(err, res) {
    if (err) throw err;
    console.log("文档插入成功");
    db.close();
  });
//查询数据
//指定条件数据
 var whereStr = {"name":'菜鸟教程'};  // 查询条件
  dbo.collection("site"). find(whereStr).toArray(function(err, result) { // 返回集合中所有数据
      if (err) throw err;
      console.log(result);
      db.close();
  });
// 更新一条数据
// 如果要更新所有符合条的文档数据可以使用 updateMany():
    var whereStr = {"name":'菜鸟教程'};  // 查询条件
    var updateStr = {$set: { "url" : "https://www.runoob.com" }};
    dbo.collection("site").updateOne(whereStr, updateStr, function(err, res) {
        if (err) throw err;
        console.log("文档更新成功");
        db.close();
    });
//删除一条数据
    var whereStr = {"name":'菜鸟教程'};  // 查询条件
    dbo.collection("site").deleteOne(whereStr, function(err, obj) {
        if (err) throw err;
        console.log("文档删除成功");
        db.close();
    })
// 如果要删除多条语句可以使用 deleteMany() 方法

更多操作和说明可参见:https://www.runoob.com/nodejs/nodejs-mongodb.html
可视化工具下载: http://www.treesoft.cn/dms.html
demo案例 - 使用MySQL数据库的登录注册系统

st=>start: 开始
e1=>end: 进入页面
op1=>operation: 登录
op2=>operation: 登录成功
op3=>operation: 登录失败
op4=>operation: 注册
op5=>operation: 注册成功
op6=>operation: 注册失败
cond1=>condition: 数据库是否存在该用户
cond2=>condition: 数据库是否存在该用户
st->op1->cond1
cond1(yes)->op2->e1
cond1(no)->op3->op4->cond2->cond2(no)->op5
cond2(yes)->op6->op4

node.js与redis的互联互通

  • Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种
    语言的API。
  • Redis 与其他 key - value 缓存产品有以下三个特点:
    • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
    • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
    • Redis支持数据的备份,即master-slave模式的数据备份
  • 优势
    • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
    • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
    • 原子 – Redis的所有操作都是原子性[4]的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
    • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

以上资料均来自网上
Window 下安装
下载地址:https://github.com/MSOpenTech/redis/releases
Redis 支持 32 位和 64 位。
Redis教程: http://www.redis.net.cn/tutorial/3501.html
可视化工具下载: http://www.treesoft.cn/dms.html

demo案例 - Nodejs+Redis+socketio的聊天室和订阅模式

技术要点:

  • 开启服务、连接Redis数据库
var redis = require('redis');
var http = require('http');
var socketio = require('socket.io');
// 开启服务
var server = http.createServer(function (req, res) {
  res.writeHead(200, {
    'Content-Type': 'text/plain'
  });
  res.end('服务器开启成功');
}).listen(4000);
// 连接Redis数据库
var redisPool = redis.createClient(6379, '127.0.0.1', {});
// 数据库的密码
redisPool.auth('123456');
// 共用16个数据库
redisPool.select(1, function () {
  console.log('选择数据库第2个数据库');
});
redisPool.on('connect', function () {
  console.log('Redis连接成功.');
})
var io = socketio(server);
io.on('connection', function (socket) {
  console.log('socketio已连接成功');
// 后续的操作都这里进行
})
  • 连接socketio
<script src="https://cdn.bootcss.com/socket.io/2.1.0/socket.io.js"></script>

socket = io.connect('http://127.0.0.1:4000');
socket.on('connect', function () {
// socket与后端成功建立链接 
});

订阅模式

  • 后台
// 消息订阅者,即subscribe客户端,需要独占链接,
  var subscribe = redis.createClient();
  subscribe.auth('123456');
//scoket监听订阅者在客户端订阅一个channel  
  socket.on('subscribe', function (channel, username) {
    //这里我们把用户每次订阅的channel放到了一个set中
    credis.sadd('user:' + username, channel); 
    // 给前端发送消息
    socket.emit('message', {});
    subscribe.subscribe(channel);
  }) 

  • 前端
// 订阅
var socket.emit('subscribe', channel, username);
// 接受消息
socket.on('message', function (message) {

})

取消订阅

  • 后台
 //scoket监听订阅者在客户端取消订阅一个channel  
  socket.on('unsubscribe', function (channel, username) {
    socket.emit('message', {});
    subscribe.unsubscribe(channel);
  })
  • 前端
 socket.emit('subscribe', channel, username);

发布消息

//消息发布者,即publish客户端,无需独占链接
  var publish = redis.createClient();
  publish.auth('123456');
// 当前发布者向某一个channel中发布消息,
publish.publish(channel, data);
//发布者在某个channel发送消息的时候,订阅频道的redis链接监听这个消息和该频道  
subscribe.on('message', function (channel, message, pattern) {
    socket.emit('message', {})
})

redis作为缓存对消息的存储和查询
根据5种数据类型有不同的存储和查询方法:

  1. string(字符串)
redisPool.set('test-key', '12354', function (err) {
});
redisPool.get('test-key', function (err, reply) {
    console.log(reply);
});
  1. hash(哈希)
redisPool.hset('hashKey', "field1", "someValue124", redis.print);
redisPool.hmset("keys", ["test keys 1", "test val 1", "test keys 2", "test val 2"], function (err, res) {

});
redisPool.hgetall('hashKey', function (err, replies) {
  console.log(replies);
});
  1. list(列表)
// 头部(左边 lpush)或者尾部(右边 rpush)
redisPool.lpush('runoobs', "rediss", function (err, reply) {
  console.log(reply);
});
redisPool.rpush('runoobs', 'valuess', function (err, reply) {
  console.log(reply);
});
redisPool.lrange('runoobs', 0, 10, function (err, reply) {
  console.log(reply);
});
  1. Set(集合)
redisPool.sadd('runoob', ['redis', '456', 'mongodb', '798'], function (err, reply) {
  console.log(reply);
});
redisPool.smembers('runoob', function (err, reply) {
  console.log(reply);
});
  1. zset(sorted set:有序集合)
redisPool.zadd('runoobz', 1, 'mongodb', function (err, reply) {
  console.log(reply);
});
redisPool.zrangebyscore('runoobz', 0, 100, function (err, reply) {
  console.log(reply);
});
  • 升级方案(优化)
  1. 增加了群发和点对点发送(以名字为唯一标识符)
  2. 页面的优化
  3. 对已订阅的客户端定时发送消息,需要socketio连接的外面执行
setInterval(function () {
    publishs.publish('订阅者', '发布的消息');
}, 1000 * 5);

更多教程可参见: http://www.runoob.com/redis/redis-sets.html

源代码下载地址: https://gitee.com/ityangzhiwen/knowledge-redis-mongodb-mysql

技术分享markdown页面下载地址:https://gitee.com/ityangzhiwen/technology_sharing


  1. Node.js Wiki .维基百科[引用日期2014-01-09]

  2. NodeJS无所不能:细数十个令人惊讶的NodeJS开源项目 .TechTarget[引用日期2015-10-31]

  3. 分布式文档存储数据库 MongoDB .开源社区网[引用日期2012-09-08]

  4. 什么是原子性,什么是原子性操作?
    举个例子:
    A想要从自己的帐户中转1000块钱到B的帐户里。那个从A开始转帐,到转帐结束的这一个过程,称之为一个事务。在这个事务里,要做如下操作:
    1.. 从A的帐户中减去1000块钱。如果A的帐户原来有3000块钱,现在就变成2000块钱了。
    2.. 在B的帐户里加1000块钱。如果B的帐户如果原来有2000块钱,现在则变成3000块钱了。
    如果在A的帐户已经减去了1000块钱的时候,忽然发生了意外,比如停电什么的,导致转帐事务意外终止了,而此时B的帐户里还没有增加1000块钱。那么,我们称这个操作失败了,要进行回滚。回滚就是回到事务开始之前的状态,也就是回到A的帐户还没减1000块的状态,B的帐户的原来的状态。此时A的帐户仍然有3000块,B的帐户仍然有2000块。
    我们把这种要么一起成功(A帐户成功减少1000,同时B帐户成功增加1000),要么一起失败(A帐户回到原来状态,B帐户也回到原来状态)的操作叫原子性操作。
    如果把一个事务可看作是一个程序,它要么完整的被执行,要么完全不执行。这种特性就叫原子性。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343