私は、ソーシャル関連アプリケーションの大部分が投稿を持っているように、人々が投稿を高く評価してコメントできるシステムを設計しています。また、大多数のアプリケーションと同様に、ユーザーは投稿が取得したいいね/コメントの数を確認できます。
問題は、これらの数値を表示するには、投稿が読み込まれるたびにすべてのいいねやコメントをカウントするか、投稿にカウンターを保持する必要があることです。
毎回いいねやコメントを数えるのはパフォーマンスが悪いと思うので、2番目の解決策を選ぶことにしました。ただし、投稿にはカウンターを保存する必要があるため、誰かが投稿を高く評価するたびに、バージョンを更新する必要があります。
複数の人が一度に投稿を操作できるため、OptimisticLockingExcpetionsの発生率が高くなり、ユーザーを苛立たせるのではないかと心配しています。
皆さんはどう思いますか?
あなたは正しいです-それは起こります。しかし、私はあなたが投稿のために楽観的ロックを必要としないと思います。 AFAICT、ソーシャルネットワークでは、ユーザーが生成したコンテンツを変更できるのは、所有者/投稿者自身だけです。したがって、競合を書くことは実際の問題ではありません。これらのエンティティのロックを無効にすることができます。
カウンターを正しくするために、カウンターをインクリメント/デクリメントするのではなく、好き/嫌いごとに再カウントします。
UPDATE posts SET nLikes = (SELECT COUNT(*) FROM likes_posts WHERE post_id = :postId) WHERE id = :postId
投稿やコメントのいいねを追跡するシングルトンのサービスクラスを作成します。定期的にデータをデータベースにフラッシュします。
class LikeService {
// format: <pk, nlikes>
HashMap<Integer, Integer> cachePostLikes = new HashMap<Integer,Integer>();
HashMap<Integer, Integer> cacheCommentLikes = new HashMap<Integer,Integer>();
HashMap<Integer, Integer> dbPostLikes = new HashMap<Integer,Integer>();
HashMap<Integer, Integer> dbPostLikes = new HashMap<Integer,Integer>();
void incrementPostLikes() {}
void incrementCommentLikes() {}
Long getPostLikes(Integer postId) {
if(!cachePostLikes.containsKey(postId)) {
// load from db
}
return cachePostLikes.get(postId) + dbPostLikes.get(postId)
}
Long getCommentLikes(Integer commentId) {}
// Always reset counts in cache hashmaps to zero
void flushToDB() {}
}