🦁
相変わらず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