【问题标题】:Redis not caching, going to MongoDB every time insteadRedis不缓存,每次都去MongoDB
【发布时间】:2021-01-08 22:40:41
【问题描述】:

我正在尝试启动并运行 Redis,并且我的服务器正在运行。但是,当我运行负载测试时,我发现每个查询仍然会发送到我的 mongoDB,而不是先查看 Redis。我的 Redis 服务器终端是这样的:

41136:M 22 Sep 2020 14:00:00.641 * Background saving terminated with success
41136:M 22 Sep 2020 14:01:01.074 * 10000 changes in 60 seconds. Saving...
41136:M 22 Sep 2020 14:01:01.076 * Background saving started by pid 42406
42406:C 22 Sep 2020 14:01:05.256 * DB saved on disk
41136:M 22 Sep 2020 14:01:05.305 * Background saving terminated with success
41136:M 22 Sep 2020 14:02:06.043 * 10000 changes in 60 seconds. Saving...
41136:M 22 Sep 2020 14:02:06.052 * Background saving started by pid 42439
42439:C 22 Sep 2020 14:02:10.719 * DB saved on disk
41136:M 22 Sep 2020 14:02:10.784 * Background saving terminated with success
41136:M 22 Sep 2020 14:03:11.030 * 10000 changes in 60 seconds. Saving...
41136:M 22 Sep 2020 14:03:11.033 * Background saving started by pid 42480
42480:C 22 Sep 2020 14:03:17.592 * DB saved on disk
41136:M 22 Sep 2020 14:03:17.690 * Background saving terminated with success

但是,当我查看我的 New Relic 仪表板时,我发现响应时间非常慢(至少 10,000 毫秒),而这一切都来自 MongoDB。 Redis只占用15-16ms左右,另外10000ms是MongoDB。

但是,我的 MongoDB 索引正确,因为那里的查询只需要 1 毫秒。我还在我的 database.js 文件中使用了 .lean() 方法。

我正在使用 Artillery 进行负载测试。

作为参考,这是我的服务器的 index.js 文件:

require('newrelic');
const express = require('express');
const bodyParser = require('body-parser');
const Images = require('../database-mongo/index.js');
const cors = require('cors');
const redis = require('redis');
const client = redis.createClient();
const RedisServer = require('redis-server');

const server = new RedisServer(6379);
const PORT = 3003;

const app = express();
app.use(cors());

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.use(express.static(__dirname + '/../react-client/dist'));

server.open((err) => {
  if (err === null) {
    console.log('redis server working')
  }
})

let redisMiddleware = (req, res, next) => {
  let key = "__expIress__" + req.originalUrl || req.url;
  client.get(key, function (err, reply) {
    if (reply) {
      res.send(reply);
    } else {
      res.sendResponse = res.send;
      res.send = (body) => {
        client.set(key, JSON.stringify(body));
        res.sendResponse(body);
      }
      next();
    }
  });
};


app.get('/images/urls/:itemId', redisMiddleware, (req, res) => {
  Images.fetchItemImages(Number(req.params.itemId))
    .then((data) => {
      if (data) {
        res.status(200).send({ data });
      } else {
        res.sendStatus(404);
      }
    })
    .catch((err) => {
      console.log('error with app.get: ', err);
      res.status(500).send(err);
    })
})

app.listen(PORT, () => {
  console.log(`listening on port ${PORT}`);
});

module.exports = app

这是我的数据库的 index.js 文件:

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/images', { useNewUrlParser: true, useUnifiedTopology: true });

var db = mongoose.connection;

db.on('error', function (err) {
  console.log('mongoose connection error: ', err);
});

db.once('open', function () {
  console.log('mongoose connected successfully');
});

const imageSchema = new mongoose.Schema({
  itemId: Number,
  pic1Small: String,
  pic1Med: String,
  pic1Large: String,
  pic2Small: String,
  pic2Med: String,
  pic2Large: String
});

const Image = mongoose.model('url', imageSchema);


function fetchItemImages(itemId) {
  // console.log('fetchImages invoked')
  return Image.find({ 'itemId': Number(itemId) }).lean()
}

module.exports = Image;
module.exports.fetchItemImages = fetchItemImages;

【问题讨论】:

    标签: node.js mongodb mongoose redis


    【解决方案1】:

    我找到了解决方案。缺少两部分。首先,Redis 中间件需要有一行在返回 JSON 时解析它,所以它应该是这样的:

    let redisMiddleware = (req, res, next) => {
      let key = "__expIress__" + req.originalUrl || req.url;
      client.get(key, function (err, reply) {
        if (reply) {
          res.send(JSON.parse(reply));
        } else {
          res.sendResponse = res.send;
          res.send = (body) => {
            client.set(key, JSON.stringify(body));
            res.sendResponse(body);
          }
          next();
        }
      });
    };
    

    其次,假设Redis数据库中有数据,GET请求需要有.set方法。

    app.get('/images/urls/:itemId', redisMiddleware, (req, res) => {
      db.fetchItemImages(req.params.itemId)
        .then((data) => {
          if (data) {
            client.set(req.params.itemId, JSON.stringify({ data }))
            res.status(200).send({ data });
          } else {
            res.sendStatus(404);
          }
        })
        .catch((err) => {
          console.log('error with app.get: ', err);
          res.status(500).send(err);
        })
    })
    

    所发生的事情是没有任何东西被保存到 Redis,所以当炮兵测试中的每个测试都检查 Redis 时,没有任何东西输入到 Redis 中。

    【讨论】:

      猜你喜欢
      • 2020-04-22
      • 2019-01-19
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多