【问题标题】:Redis using 100% CPU after 6 hours of uptime正常运行 6 小时后 Redis 使用 100% CPU
【发布时间】:2020-06-04 02:29:03
【问题描述】:

如上图所示,我在 Redis 运行一段时间后遇到了性能问题;特别是 6 小时。

我正在使用 Redis 缓存来自 API 的响应,因此我不必在每个请求上重新获取数十行,我想 - 嘿,这应该可行。显然没有。

module.exports = (app, csrfProtection, jsonParser) => {
    app.get("/api/steam/getPlayerSummaries", [steamRateLimits.getPlayerSummaries, jsonParser, csrfProtection], async(req, res) => {
        redisClient.hmget("steam_user", req.query.steamids, (err, reply) => {
            if(err) return res.status(500).send({ message: `Could not read from Redis with error ${err}`});

            redisClient.hmget(`steam_user_expires_${req.query.steamids}`, "expires", (err, expire) => {
                if(err) return res.status(500).send({ message: `Could not read from Redis with error ${err}`});

                if(reply[0] && (CURRENT_UNIX_TIME - expire < REDIS_EXPIRE_LIMIT)) return res.status(200).send(JSON.parse(reply));

                const queryParams = querystring.stringify({
                    key: process.env.STEAM_API_KEY,
                    steamids: req.query.steamids
                }),
                options = {
                    headers: {
                        "Content-Type": "application/x-www-form-urlencoded"
                    }
                };

                http.get(`http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?${queryParams}`, options, response => {
                    const { statusCode } = response;

                    if(statusCode != 200) {
                        response.resume();
                        return res.status(statusCode).send({ message: `Could not fetch Steam API getPlayerSummaries with status code ${statusCode}`});
                    }

                    response.setEncoding("utf8");
                    let rawData = "";

                    response.on("data", chunk => rawData += chunk);
                    response.on("end", _ => {
                        try {
                            const parsedData = JSON.parse(rawData);

                            redisClient.hmset(["steam_user", req.query.steamids, rawData]);
                            redisClient.hmset([`steam_user_expires_${req.query.steamids}`, "expires", CURRENT_UNIX_TIME]);

                            return res.status(200).send(parsedData);
                        } catch (e) {
                            console.error(e.message);
                        }
                    });
                }).on("error", e => {
                    console.error(`Got error: ${e.message}`);
                    return res.status(500).send(e);
                });
            });
        });
    });
}

以下是用户尝试访问此路线时按时间顺序发生的进度概览:

  1. 用户加载索引(默认)网页。这个页面可以有20多个 需要从远程 API 运行 20 个 API 查询的行(其中一个 我缓存这个的原因)。
  2. 检查用户是否已经缓存在redis中
  3. 检查是否存在上述 Steam 用户的过期密钥(即使不存在)。
  4. 如果缓存存在并且它是在不到 15 分钟前提取的,则显示来自 Redis 缓存的结果。
  5. 如果缓存不存在,我们会查询远程 API。
  6. 如果请求成功,将数据缓存到 Redis 并返回响应。

由于某种原因,这本身就陷入了困境,并且在运行 Redis 一段时间后使用了如此多的 CPU 和 RAM,这太疯狂了,我认为我处理得当。

我还使用 shell 脚本和 crontab 每天清除一次所有缓存。

redis-cli KEYS "steam_user*" | xargs redis-cli DEL

为什么它会继续消耗更多的 CPU 和 RAM(即使实际上没有访客,而且我不敢想象如果有很多访客会发生什么),我该如何解决这个问题修复它?

【问题讨论】:

    标签: javascript node.js redis


    【解决方案1】:

    使用所有资源的进程是 /tmp/kdevtmpfsi。快速的谷歌搜索表明它正在挖掘恶意软件。这意味着 Redis 和您的程序都没有出现某种错误。 This Github 上的评论解释了如何摆脱它。

    【讨论】:

    • 谢谢!我什至没有使用 docker,它是来自 vultr 的新服务器。真的很惊讶有人能这么快找到它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多