🦁

相変わらずRedisに苦戦している

に公開

初めに

お疲れ様です。
引き続き投票の仕様について悩んでいます。
DBに毎回アクセスしてしまう問題を解決していきたいです。

現状の課題

    await postVotes(voteType);
    await updateVotes();

postVotesを呼び出したとき

  def perform(post_id)
    redis_key = "post_#{post_id}_votes"
    $redis.del(redis_key) # Redisのキャッシュを削除
  end

updateVotesを呼び出したとき

  def self.get_votes(post_id)
    redis_key = "post_#{post_id}_votes"
    cached_votes = $redis.get(redis_key)
    return JSON.parse(cached_votes) if cached_votes

    # キャッシュがない場合はDBから取得
    post = Post.find_by_id(post_id)
    votes = Vote.vote_counts(post)

    # キャッシュに保存(10分間)
    $redis.set(redis_key, votes.to_json)
    $redis.expire(redis_key, 10.minutes.to_i)

    votes
  end

このようになっています。
postVotesを呼び出すことで、古いキャッシュを削除しているのに削除した後すぐにupdateVotesを呼び出しています。これで何が起きるかというと、キャッシュが存在しないのでDBから再計算して値を取得しています。

これ、結局毎回DBから呼び出してるからキャッシュの意味ないじゃねーか!!!

となったわけです。
なんか変だなと5時間ほど思い悩んでいたところこういうことでした。

ではどうするか

理想は投票直後の見た目はフロントエンドの状態管理を使って、投票が見た目だけ増減するようにします。
そして、リロード時のみデータを取得してページに反映させるという方法を取りたいと思います。

結果

  useEffect(() => {
    const fetchVotes = async () => {
      const votes = await getVotes();
      const goodVotes = votes.good;
      const badVotes = votes.bad;

      setUpvotes({ [post_id]: goodVotes });
      setDownvotes({ [post_id]: badVotes });
    };
    fetchVotes();
  }, [getVotes, post_id, setDownvotes, setUpvotes]);

こんな感じでフロントエンドは
投票した際はupdateVotesを呼ぶのをやめて、postVotesだけを呼び、
updateVotesはuseEffectで管理することで、画面にリロードが入ったときのみ投票数の更新を行えるようになった!

Discussion