Cassandra and social "unfriend" / "unfollow"

Viewed 474

Intro

I'm getting to know Cassandra a bit more and creating a simple social network (similar to Instagram/Facebook).

The general idea is, you can follow/friend people and see their updates in a feed. When launching an application, you should be able to scroll through the feed (updates sorted by time) and paginate it.

In my case I'm sticking with the fan-out approach - whenever an update is being published, it will be pushed to the feeds of friends/followers.

Here's what my schema looks like.

CREATE TABLE feed_by_time (
    user_id uuid,
    time timestamp,
    author_id uuid,
    post_id uuid,
    PRIMARY KEY  (user_id, time, author_id)
) WITH CLUSTERING ORDER BY (time DESC);

With this table, I should be able to get any users' feed easily and in sorted order, as well as paginate it further, and each users' feed will reside in its own partition, so I will not fetch from multiple nodes. I am a bit limited by the potential size of each partition, but let's assume it's not a problem right now.

Problem

Now, the actual problem - how should unfollow/unfriend functionality be implemented? It assumes that all the posts of a specific "author" should disappear from your feed.

I know that with the feed_by_time table I will not be able to delete all the posts of a specific "author" so I can have another one like:

CREATE TABLE feed_by_author (
    user_id uuid,
    author_id uuid,
    post_id uuid,
    time timestamp,
    PRIMARY KEY ((user_id, author_id), post_id)
);

and write to them at the same time, when a new post is published.

When I unfollow someone, I can do something like

  1. SELECT * FROM feed_by_author WHERE user_id="user_id" AND author_id="unfriended_id"
  2. Extract time for query result entry and run A LOT of DELETE queries towards feed_by_time
  3. Run one big DELETE to clean-up feed_by_author (in this case it will remove the entire partition)

My worry is mostly around the second point. I read that I should avoid such deletes since they are extremely costly. So, should I be worried, and are there more efficient/correct ways of doing this? Would having a deleted column, and setting it's value to 1 via UPDATE be more efficient?

Follow-up

As a follow up to this question - say, I re-follow/re-friend someone. This will result in a lot of INSERT into the feed_by_time user-specific partition since we will be effectively merging the entire author feed into the users feed. The time value on each post can vary a lot, so we can be inserting it in the "middle" of the partition. Is it costly in terms of performance?

Thanks! :)

1 Answers

you should have a table friendships

user_id
friend_id

and a table posts

post_id
user_id
post_text
date

to follow:

insert into friendships ( user_id, friend_id) values (whatevermyid, whateverfriendid)

when you want to get the feed of the user:

select post_id, post_text, date, friend_id from friendships f join posts p on f.friend_id=p.user_id and f.user_id=whatevermyid order by date desc

when you unfollow someone:

delete from friendships where friend_id=whateverfriendid and user_id=whatevermyid

which will actualy be one record

Related