簡體   English   中英

Redis 在 6 小時正常運行后使用 100% CPU

[英]Redis using 100% CPU after 6 hours of uptime

在此處輸入圖片說明

如上圖所示,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(即使實際上沒有訪問者,而且我不敢想象如果有很多訪問者會發生什么),我該如何解決這個問題來解決它?

使用您所有資源的進程是 /tmp/kdevtmpfsi。 快速谷歌搜索顯示它正在挖掘惡意軟件。 這意味着不是 Redis 也不是你的程序有某種錯誤。 Github 上的這個評論解釋了如何擺脫它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM