3

I'm designing a system that like the majority of social related application has posts, people can like the posts and comment on them. And also like the majority of the applications the users can see how many like/comments a post got.

The problem is that to show these numbers I would have to count all the likes and comments every time a post is loaded or keep counters in the posts.

I think that counting the likes and comments every time will be bad performance wise so I decided to go with the second solution. But because the posts now have to store the counters, every time someone likes a post the version will have to be updated.

I'm worried that since multiple people can interact with a post at once the occurence of OptimisticLockingExcpetions can be high and it will annoy my users.

What do you guys think?

Lucas Piske
  • 371
  • 3
  • 10

2 Answers2

2

You are correct - that will occur. But i think that you dont need optimistic locking for the posts. AFAICT, social networks allow the user generated content to be altered only be the owner/poster themselves. Writing conflicts should therefore not be a real issue. You can disable locking for those entities.

In order to get the counter correct, re-count with every like/dislike instead of incrementing/decrementing the counter:

UPDATE posts SET nLikes = (SELECT COUNT(*) FROM likes_posts WHERE post_id = :postId) WHERE id = :postId
marstato
  • 4,538
  • 2
  • 15
  • 30
  • Hi @marstato, thanks for your answer, but counting the likes every time that a new like happens looks like that it will be a problem for posts with a high amount of likes. – Lucas Piske Feb 27 '17 at 02:12
  • Why would it? Many-To-Many association tables are bery easy to Count because there is no variable sized Data in them. Theres an index on the Id column anyways because they are BN foreign keys. This should perform very well up to hundrets of thousands of likes - considering that the average post hast far less. – marstato Feb 27 '17 at 07:48
0

Create a service class that is a singleton that keeps track of likes on posts, comments. Periodically flush the data to the database.

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() {}
}