user2896120
user2896120

Reputation: 3282

Storing user views in Redis

I have a website that has a feed with posts. When a user looks at a post for longer than 3 seconds, then that counts as a view. A request will be made and stored into Redis as this format:

user_id: [1,4,5]

Where user_id is the key and the array is a set that stores a list of the user's viewed posts. I believe this is a very simple approach, however, I believe in the long run the set for each user will get very, very long. Currently, my site is not big. I'm powering it on 1GB RAM and 1 core. I know in the short-term I won't exceed any of my hardware limits, but I was wondering if this is a good design or if there's a better way of storing user views. The reason I chose Redis is because making a request to store data in a SQL database would be slower compared to storing in Redis.

Upvotes: 1

Views: 997

Answers (1)

Ersoy
Ersoy

Reputation: 9624

In your case and in your scale, analytics processing, redis would be sufficient until a significant scale and scenarios. I would still recommend to start with postgresql or yandex clickhouse for extensive querying capabilities and better data structures in terms of analytics.

Since you may have future plans to make top posts(weekly, monthly, all time or user based) you may need a history of all the interactions between users and posts. After 8 months when you decide to make top posts depending on user segments, time interval, or other factors - you will need that history. In redis sets you won't have it. If you want to have it, then you will need additional sets/sorted sets to keep track of post-user relations. Whenever you add a new post to user's set, then you need to add that post to post's user's sorted set. I think seeing the same posts in different times should be also another consideration in that case.

127.0.0.1:6379> sadd user:1 post1 post2 post3 post4
(integer) 4
127.0.0.1:6379> sadd user:1:posts post1 post2 post3 post4
(integer) 4
127.0.0.1:6379> zadd post1:users 1589791701 user:1
(integer) 1
127.0.0.1:6379> zadd post2:users 1589791701 user:1
(integer) 1
127.0.0.1:6379> zadd post3:users 1589791701 user:1
(integer) 1
127.0.0.1:6379> zadd post4:users 1589791701 user:1
(integer) 1
127.0.0.1:6379> zrange post1:users 0 -1 withscores
1) "user:1"
2) "1589791701"
127.0.0.1:6379>

If the user base grows then you need to query with spop, smembers or srandmember to fetch those posts - but i am not sure will it meet your expectations - since you can't paginate(without using spop and moving into another set). If you need to query depending on the multiple users - then you need to keep track of all the users to query their sets (you may already have it) - intersections etc.

If you are decisive about going with redis; then you may consider to use lists for better pagination, keeping count of post views with incrby/hincrby.

The key point is history, and the querying capabilities of the history in distributed keys across all the cluster. In your case you need to do some additional work to keep that history active.

Upvotes: 1

Related Questions