Nodejs中使用ioredis库

断了今生、忘了曾经 提交于 2020-12-05 18:00:30

前言

Redis简介

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings)散列(hashes)列表(lists)集合(sets)有序集合(sorted sets) 与范围查询, bitmapshyperloglogs地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication)LUA脚本(Lua scripting)LRU驱动事件(LRU eviction)事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

查看Redis命令大全 → 访问Redis论坛 → Redis使用内存计算器 →

应用场景

最近工作中使用Nodejs编写后端程序操作redis,从redis缓存中获取对应的站房的监测环境数据,然后再提供http和websocket接口,提供给前端获取并实时展示。刚开始使用的是node-redis这个库,其对应的github地址是:https://github.com/NodeRedis/node-redis,npm官网地址是:https://www.npmjs.com/package/node-redis,后来发现了国内阿里的一个Nodejs的redis库,其npm官网地址是:https://www.npmjs.com/package/ioredis,ioredis库比node-redis更新维护快并且比较新,所以就改用ioredis库了。

从redis缓存中获取对应的站房的监测环境数据,然后再提供http接口,返回所有的站房监测数据,获取可以根据某个站点编码返回对应的站房监测数据 根据数据类型(用datatype表示),站房环境数据的数据缓存结构的datatype为env 所有的数据存储都是以key-value键值对形式存储在Redis中,编码为UTF8。数据存储的key结构都是一致的,形式为 “数据类型:解析类型:站点编码:日期(yyyyMMdd):时间(HHmmss)”

数据存储value键都是以hash方式存储,其中field为数据标识, value为数据值。 监测数据的field根据解析类型有两种形式,如下

  • “监测项名称” 监测数据的value根据解析类型有两种形式,如下 “监测项名称|数值|标记|平台监测因子编码|平台监测因子单位标识”

站房环境数据结构在redis中存储的形式如下图所示: 站房环境数据结构

1、使用node-redis库

使用npm或cnpm安装依赖

$ npm install node-redis

相关的nodejs代码node_redis_client_demo.js如下所示:

var express = require('express');
var app = express();
var http = require('http').Server(app);
var port = process.env.PORT || 3001;

const redis = require('redis')

http.listen(port, function(){
  console.log('listening on localhost:' + port);
})

const redisClient = redis.createClient({
  host: '127.0.0.1',
  port: 6379,
  password: '1234',
  db: 3
});

// 站房环境数据信息
const envData = {
  CylinderGasPress3: 'CylinderGasPress3|9.05||EP126|', 
  IA: 'IA|7.80||EP117|',
  SmokeState: 'SmokeState|0||EP113|',
  CylinderGasPress: 'CylinderGasPress|7.58||EP124|',
  StationHum: 'StationHum|39.59||EP121|',
  VB: 'VB|225.24||EP115|',
  PipeTemp: 'PipeTemp|32.50||EP122|',
  VC: 'VC|224.05||EP116|',
  IB: 'IB|7.34||EP118|',
  SwitchState: 'SwitchState|1||EP111|',
  PipeHum: 'PipeHum|20.10||EP123|',
  VA: 'VA|225.93||EP114|',
  Water1: 'Water1|1||EP112|',
  StationTemp: 'StationTemp|28.60||EP120|',
  AlarmState: 'AlarmState|0||EP110|',
  CylinderGasPress2: 'CylinderGasPress2|6.33||EP125|',
  IC: 'IC|2.92||EP119|'
}

// 站房环境信息
var lastenvBuff = {};

// 写入Javascript(JSON)对象
// 站房环境监测数据(测试3个站点)
redisClient.hmset('env:hbxd:420100401:20200409:100901', envData, function(err){
  console.log(err)
})

redisClient.hmset('env:hbxd:421000405:20200409:172000', envData, function(err){
  console.log(err)
})

redisClient.hmset('env:hbxd:422800408:20200409:172800', envData, function(err){
  console.log(err)
})

// 读取Javscript(JSON)对象
// redisClient.hgetall('env:*', function (err, object) {
//   console.log(object)
// })

redisClient.keys('env:*', function(err,keys){
  console.log(keys)
    // 打印所有的站房环境数据的redis key
    console.log(keys);
    // 遍历站房环境数据的keys数组
    for (let i = 0; i < keys.length; i++) {
      // 从keys中解析得到站点编码、数据时间等信息
      const strArrayTemp = keys[i].split(':');
      const strstcode = strArrayTemp[2];

      const strdataTime = strArrayTemp[3] + strArrayTemp[4];

      // 将数据时间从 20200228135130 转换成 2020-02-28 13:51:30 的格式
      let year = strdataTime.substr(0, 4);
      let month = strdataTime.substr(4, 2);
      let day = strdataTime.substr(6, 2);
      let hour = strdataTime.substr(8, 2);
      let minute = strdataTime.substr(10, 2);
      let second = strdataTime.substr(12, 2);

      // let date = Date();
      //timestamp = moment().format('YYYY-MM-DD HH:mm:ss');
      var strTimestamp = year + '-' + month + '-' + day + ' ' + hour + ':' + minute+ ':' + second;
      
      // 根据每一个hash key获取到对应的filed和value
      // hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value
      redisClient.hgetall(keys[i], function(err,obj) {
        var envMonitorArr = []; // 当前站点的站房监测因子信息数组
        console.log('第' + (i+1) + '个站点的站点编码为:' + strstcode + ',数据时间为:' + strTimestamp);
        // 遍历某个站点的所有站房监测信息
        for (var pkey in obj) {
          // console.log('field:' + pkey + ',value:' + obj[pkey]);
          // 从value中解析出监测因子编码,数值,标记位,单位
          var strValArray = obj[pkey].split('|');
          var sValue = strValArray[1];
          var strMark = strValArray[2];
          var strParamCode = strValArray[3];
          var strUnit = strValArray[4];
          console.log('监测因子编码:' + strParamCode + ',数值:' + sValue + ',标记位:' + (strMark ? strMark: 'N'));
          // 将站房监测因子添加到监测因子数组中
          envMonitorArr.push({
            'code': strParamCode,
            'value': sValue,
            'mark': strMark ? strMark: 'N'
          })
        }
        var jsonObj = {
          'stcode': strstcode,
          'time': strdataTime,
          'envList': envMonitorArr
        }

        // 缓存每个站点的站房的最新数据
        var env_data_arr = [];
        env_data_arr.push(Object.assign({}, jsonObj));
        // 遍历站房缓存数据数组
        for (var ii = 0; ii < env_data_arr.length; ii++) {
          var iitem = env_data_arr[ii];
          console.log('站房监测信息:' + JSON.stringify(iitem));
          var stacode = iitem.stcode;
          if (!(stacode in lastenvBuff)) {
            lastenvBuff[stacode] = {'stcode': stacode, 'time': strTimestamp, 'envList': iitem.envList};
          } else {
            if (strdataTime > lastenvBuff[stacode].time) {
              lastenvBuff[stacode] = {'stcode': stacode, 'time': strTimestamp, 'envList': iitem.envList};
            }
          }
        }
        // 打印当前所有站点的站房环境信息
        console.log(JSON.stringify(lastenvBuff))
      })
    }
})

// 获取某个站点的最新的站房环境数据
app.get('/api/envData/:stcode', function (req, res) {
  console.log(req.params)
  // 获取客户端传过来的站点编码
  var stcode = req.params.stcode
  // 以站点编码为key,返回缓存中的历史报警记录
  res.send(lastenvBuff[stcode]);
});

// 获取当前所有站点的站房环境数据
app.get('/api/allEnvData/', function (req, res) {
  res.send(lastenvBuff);
});

2、使用ioredis库

使用npm或者cnpm安装ioredis库

$ npm install ioredis

对应的noejs代码ioredis_client_demo.js如下:

var express = require('express');
var app = express();
var http = require('http').Server(app);
var port = process.env.PORT || 3001;

http.listen(port, function(){
  console.log('listening on localhost:' + port);
})

const Redis = require("ioredis");
// redis配置
const redisConfig = {
  host: "127.0.0.1", // Redis host
  port: 7001, // Redis port
  password: "1234",
  db: 4,
  retryStrategy: function(times){
    return Math.min(times * 50, 5000)
  },
  // enableOfflineQueue: false
}
const redisClient = new Redis(redisConfig); // uses defaults unless given configuration object

// 站房环境数据信息
const envData = {
  CylinderGasPress3: 'CylinderGasPress3|9.05||EP126|', 
  IA: 'IA|7.80||EP117|',
  SmokeState: 'SmokeState|0||EP113|',
  CylinderGasPress: 'CylinderGasPress|7.58||EP124|',
  StationHum: 'StationHum|39.59||EP121|',
  VB: 'VB|225.24||EP115|',
  PipeTemp: 'PipeTemp|32.50||EP122|',
  VC: 'VC|224.05||EP116|',
  IB: 'IB|7.34||EP118|',
  SwitchState: 'SwitchState|1||EP111|',
  PipeHum: 'PipeHum|20.10||EP123|',
  VA: 'VA|225.93||EP114|',
  Water1: 'Water1|1||EP112|',
  StationTemp: 'StationTemp|28.60||EP120|',
  AlarmState: 'AlarmState|0||EP110|',
  CylinderGasPress2: 'CylinderGasPress2|6.33||EP125|',
  IC: 'IC|2.92||EP119|'
}

// 站房环境信息
var lastenvBuff = {};

// 写入Javascript(JSON)对象
// 站房环境监测数据(测试3个站点)
redisClient.hmset('env:hbxd:420100401:20200409:100901', envData, function(err){
  console.log(err)
})

redisClient.hmset('env:hbxd:421000405:20200409:172000', envData, function(err){
  console.log(err)
})

redisClient.hmset('env:hbxd:422800408:20200409:172800', envData, function(err){
  console.log(err)
})

redisClient.on('connect', () => {
  console.log('成功连接到Redis')
  // 获取站房环境数据的所有key列表
  redisClient.keys('env:hbxd:*', function(err,keys){
    // 打印所有的站房环境数据的redis key
    console.log(keys);
    envKeys = keys;
    // 遍历站房环境数据的keys数组
    for (let i = 0; i < keys.length; i++) {
      // 从keys中解析得到站点编码、数据时间等信息
      const strArrayTemp = keys[i].split(':');
      const strstcode = strArrayTemp[2];

      const strdataTime = strArrayTemp[3] + strArrayTemp[4];

      // 将数据时间从 20200228135130 转换成 2020-02-28 13:51:30 的格式
      let year = strdataTime.substr(0, 4);
      let month = strdataTime.substr(4, 2);
      let day = strdataTime.substr(6, 2);
      let hour = strdataTime.substr(8, 2);
      let minute = strdataTime.substr(10, 2);
      let second = strdataTime.substr(12, 2);

      // let date = Date();
      //timestamp = moment().format('YYYY-MM-DD HH:mm:ss');
      var strTimestamp = year + '-' + month + '-' + day + ' ' + hour + ':' + minute+ ':' + second;
      
      // 根据每一个hash key获取到对应的filed和value
      // hgetall(key):返回名称为key的hash中所有的键(field)及其对应的value
      redisClient.hgetall(keys[i], function(err,obj) {
        var envMonitorArr = []; // 当前站点的站房监测因子信息数组
        console.log('第' + (i+1) + '个站点的站点编码为:' + strstcode + ',数据时间为:' + strTimestamp);
        // 遍历某个站点的所有站房监测信息
        for (var pkey in obj) {
          // console.log('field:' + pkey + ',value:' + obj[pkey]);
          // 从value中解析出监测因子编码,数值,标记位,单位
          var strValArray = obj[pkey].split('|');
          var sValue = strValArray[1];
          var strMark = strValArray[2];
          var strParamCode = strValArray[3];
          var strUnit = strValArray[4];
          console.log('监测因子编码:' + strParamCode + ',数值:' + sValue + ',标记位:' + (strMark ? strMark: 'N'));
          // 将站房监测因子添加到监测因子数组中
          envMonitorArr.push({
            'code': strParamCode,
            'value': sValue,
            'mark': strMark ? strMark: 'N'
          })
        }
        var jsonObj = {
          'stcode': strstcode,
          'time': strdataTime,
          'envList': envMonitorArr
        }

        // 缓存每个站点的站房的最新数据
        var env_data_arr = [];
        env_data_arr.push(Object.assign({}, jsonObj));
        // 遍历站房缓存数据数组
        for (var ii = 0; ii < env_data_arr.length; ii++) {
          var iitem = env_data_arr[ii];
          console.log('站房监测信息:' + JSON.stringify(iitem));
          var stacode = iitem.stcode;
          if (!(stacode in lastenvBuff)) {
            lastenvBuff[stacode] = {'stcode': stacode, 'time': strTimestamp, 'envList': iitem.envList};
          } else {
            if (strdataTime > lastenvBuff[stacode].time) {
              lastenvBuff[stacode] = {'stcode': stacode, 'time': strTimestamp, 'envList': iitem.envList};
            }
          }
        }
        // 打印当前所有站点的站房环境信息
        // console.log(JSON.stringify(lastenvBuff))
      })
    }
  })
})

// 获取某个站点的最新的站房环境数据
app.get('/api/envData/:stcode', function (req, res) {
  console.log(req.params)
  // 获取客户端传过来的站点编码
  var stcode = req.params.stcode
  // 以站点编码为key,返回缓存中的历史报警记录
  res.send(lastenvBuff[stcode]);
});

// 获取当前所有站点的站房环境数据
app.get('/api/allEnvData/', function (req, res) {
  res.send(lastenvBuff);
});

3、运行程序

保证在对应系统中安装好express和ioredis、node-redis依赖后,使用node ioredis_client_demo.js执行对应的nodejs后台程序,在localhost:3001端口上监听,提供http服务。

(1)、请求所有站房的环境数据

在浏览器中输入路径:http://localhost:3001/api/allEnvData/ 得到当前所有站点的站房环境数据,如下图所示: 获取所有站房的环境数据 完整的JSON数据如下所示:

{
420100401: {
stcode: "420100401",
time: "2020-04-09 17:28:00",
envList: [
{
code: "EP126",
value: "9.05",
mark: "N"
},
{
code: "EP117",
value: "7.80",
mark: "N"
},
{
code: "EP113",
value: "0",
mark: "N"
},
{
code: "EP124",
value: "7.58",
mark: "N"
},
{
code: "EP121",
value: "39.59",
mark: "N"
},
{
code: "EP115",
value: "225.24",
mark: "N"
},
{
code: "EP122",
value: "32.50",
mark: "N"
},
{
code: "EP116",
value: "224.05",
mark: "N"
},
{
code: "EP118",
value: "7.34",
mark: "N"
},
{
code: "EP111",
value: "1",
mark: "N"
},
{
code: "EP123",
value: "20.10",
mark: "N"
},
{
code: "EP114",
value: "225.93",
mark: "N"
},
{
code: "EP112",
value: "1",
mark: "N"
},
{
code: "EP120",
value: "28.60",
mark: "N"
},
{
code: "EP110",
value: "0",
mark: "N"
},
{
code: "EP125",
value: "6.33",
mark: "N"
},
{
code: "EP119",
value: "2.92",
mark: "N"
}
]
},
421000405: {
stcode: "421000405",
time: "2020-04-09 17:28:00",
envList: [
{
code: "EP126",
value: "9.05",
mark: "N"
},
{
code: "EP117",
value: "7.80",
mark: "N"
},
{
code: "EP113",
value: "0",
mark: "N"
},
{
code: "EP124",
value: "7.58",
mark: "N"
},
{
code: "EP121",
value: "39.59",
mark: "N"
},
{
code: "EP115",
value: "225.24",
mark: "N"
},
{
code: "EP122",
value: "32.50",
mark: "N"
},
{
code: "EP116",
value: "224.05",
mark: "N"
},
{
code: "EP118",
value: "7.34",
mark: "N"
},
{
code: "EP111",
value: "1",
mark: "N"
},
{
code: "EP123",
value: "20.10",
mark: "N"
},
{
code: "EP114",
value: "225.93",
mark: "N"
},
{
code: "EP112",
value: "1",
mark: "N"
},
{
code: "EP120",
value: "28.60",
mark: "N"
},
{
code: "EP110",
value: "0",
mark: "N"
},
{
code: "EP125",
value: "6.33",
mark: "N"
},
{
code: "EP119",
value: "2.92",
mark: "N"
}
]
},
422800408: {
stcode: "422800408",
time: "2020-04-09 17:28:00",
envList: [
{
code: "EP126",
value: "9.05",
mark: "N"
},
{
code: "EP117",
value: "7.80",
mark: "N"
},
{
code: "EP113",
value: "0",
mark: "N"
},
{
code: "EP124",
value: "7.58",
mark: "N"
},
{
code: "EP121",
value: "39.59",
mark: "N"
},
{
code: "EP115",
value: "225.24",
mark: "N"
},
{
code: "EP122",
value: "32.50",
mark: "N"
},
{
code: "EP116",
value: "224.05",
mark: "N"
},
{
code: "EP118",
value: "7.34",
mark: "N"
},
{
code: "EP111",
value: "1",
mark: "N"
},
{
code: "EP123",
value: "20.10",
mark: "N"
},
{
code: "EP114",
value: "225.93",
mark: "N"
},
{
code: "EP112",
value: "1",
mark: "N"
},
{
code: "EP120",
value: "28.60",
mark: "N"
},
{
code: "EP110",
value: "0",
mark: "N"
},
{
code: "EP125",
value: "6.33",
mark: "N"
},
{
code: "EP119",
value: "2.92",
mark: "N"
}
]
}
}

(2)、请求某个站点的站房环境数据

在浏览器中输入路径:http://localhost:3001/api/envData/421000405 得到站点421000405的站房环境数据,如下图所示: 根据站点编码获取对应的站房环境数据 对应的完整的json数据如下所示:

{
stcode: "421000405",
time: "2020-04-09 17:28:00",
envList: [
{
code: "EP126",
value: "9.05",
mark: "N"
},
{
code: "EP117",
value: "7.80",
mark: "N"
},
{
code: "EP113",
value: "0",
mark: "N"
},
{
code: "EP124",
value: "7.58",
mark: "N"
},
{
code: "EP121",
value: "39.59",
mark: "N"
},
{
code: "EP115",
value: "225.24",
mark: "N"
},
{
code: "EP122",
value: "32.50",
mark: "N"
},
{
code: "EP116",
value: "224.05",
mark: "N"
},
{
code: "EP118",
value: "7.34",
mark: "N"
},
{
code: "EP111",
value: "1",
mark: "N"
},
{
code: "EP123",
value: "20.10",
mark: "N"
},
{
code: "EP114",
value: "225.93",
mark: "N"
},
{
code: "EP112",
value: "1",
mark: "N"
},
{
code: "EP120",
value: "28.60",
mark: "N"
},
{
code: "EP110",
value: "0",
mark: "N"
},
{
code: "EP125",
value: "6.33",
mark: "N"
},
{
code: "EP119",
value: "2.92",
mark: "N"
}
]
}

4、参考资料:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!