🏃

よーわからんけどCasheで遊んでみた

2024/06/23に公開

とにかく早いAPIが作りたい!

パソコンのことなんて全くわからなかったときは、Webを使うたびに、せっかちは自分はイライラしていました。早く知りたいのにずっとくるくるなっている画面、、なぜもっと早く動かないのか、、
時が経ち、駆け出しエンジニアとして勉強中の自分ですが、APIを作成する時に毎回DBにリクエストを送るコードを書いていました。最近、無知の知を持った私は、この行為が昔の自分に腹を立てられる行為だということを知りました😱

早いAPIを作るためにキャッシュしてみよう

キャッシュってなんだ、、ということで調べてみると、

キャッシュとは、データを一時的に保存する仕組みのことです。これにより、頻繁にアクセスされるデータの読み取り速度を向上させ、システム全体のパフォーマンスを向上させることができます。

とのことです。(ChatGPT)
例えば、同じ検索(明日の天気を教えて とか)を何回もしても、結果はそう頻繁に変わるものではありません。それなのに、わざわざDBに毎回同じことを聞きに行くのは流石にDBさんもいい気持ちはしません。ましてそれが大人気アプリで世界中から同じことを聞き続けられたら、、考えるだけでゾッとします。
そこで、今回はちゃんとキャッシュして早いAPIを作ってみようと思います。

今回の仕様

今回はNews APIのというAPIを使ってみます。
興味があるキーワードを含めてNews APIを叩くと、関連するニュースが10件返ってくる、というAPIを作ってみます。

まずは普通に作る

index.js

app.get('/users/:userId/news', async (req, res) => {
  const userId = req.params.userId;
  try {
    const user = await findUserById(userId);
    if(!user){
      console.log('not found user');
      return res.status(500).send('Error not found User');
    }
    const interests = user.interests;

   const articles = await fetchNews(interests);
    if (!articles || articles.length < 10) {
      return res.status(500).send('Error fetching articles from News API');
    }

    res.json(articles);
  } catch (error) {
    console.error('Error fetching news:', error.message);
    res.status(500).send('Error fetching news');
  }
});

だいぶ省略していますが、fetchNewsでNews APIを叩いています。これでもピンピン動いています。今のままだと毎回このfetchNewsでNews APIを叩いて(=News APIがDBまでリクエストを飛ばして)いますね。
かかった時間は500msくらいでした。

キャッシュしてみた

index.js
app.get('/users/:userId/news', async (req, res) => {
  const userId = req.params.userId;
  try {
    const user = await findUserById(userId);
    if(!user){
      console.log('not found user');
      return res.status(500).send('Error not found User');
    }
    const interests = user.interests;

    // キャッシュキーを生成
    const cacheKey = `news_${userId}`;

    // キャッシュからデータを取得
    const cachedArticles = await redisClient.get(cacheKey);
    if (cachedArticles) {
      const parsedArticles = JSON.parse(cachedArticles);
      const filteredArticles = parsedArticles.filter((article) => article.type === interests);
      if (filteredArticles.length >= 10) {
        console.log('Cache hit!!');
        return res.json(filteredArticles);
      }
    }

    // キャッシュになかったらAPIから取得
    const articles = await fetchNews(interests);
    if (!articles || articles.length < 10) {
      return res.status(500).send('Error fetching articles from News API');
    }

    // 取得したニュースをキャッシュに保存
    await redisClient.set(cacheKey, JSON.stringify(articles), { EX: 300 }); // 300秒の有効期限

    res.json(articles);
  } catch (error) {
    console.error('Error fetching news:', error.message);
    res.status(500).send('Error fetching news');
  }
});

一回News APIを叩いたらキャッシュに入れる。キャッシュに溜まってたらキャッシュから取ってくるようにしました。早速試してみよう。まずは一回APIを叩いてキャッシュさせます。キャッシュが貯まったので2回目。無事ログには、 「Cache hit!!」 が出ています。どうでしょうか。

「おおおおおおお!!!!」

と思わず声が出るほど早い!!(錦糸町のドトールにいるのにまあまあの声が出てしまった)
時間はなんと5ms!!ほぼ100分の1!!恐るべしキャッシュの力、、
キャッシュの力を身をもって体験しました。

まとめ

キャッシュ恐るべし。
これから意識して使っていこう!!

Discussion