Send messages to users via FCM once per day based on their shifting time-of-day preferences without dupes, using Redis

huangapple go评论81阅读模式
英文:

Send messages to users via FCM once per day based on their shifting time-of-day preferences without dupes, using Redis

问题

上下文

我有一堆帖子,每个帖子都有点赞和踩的计数,存储在我的Postgres数据库中。我正在运行一个Gin Golang服务器,Flutter移动应用,并且正在使用FCM(Firebase Cloud Messaging)向用户发送通知。

架构问题

首先,这个问题可以很容易地解决。我只是不知道如何高效地解决它。

我想每天向每个用户发送一次最高投票的帖子。然而,我希望根据用户在应用程序中的最活跃时间发送通知(不是一次性发送,即不仅仅是每天凌晨12点)。

所以,假设我在一个名为active_times的表中跟踪每个用户的条目,该条目具有我根据他们与移动应用程序的交互时间更新的字段,例如Postgres中的time。我根据用户的活动来更新这个字段。

我的直觉告诉我,我应该在我的服务器上每隔大约2小时运行一个cron作业,查询在这个2小时窗口内具有time字段的所有用户。然后,我向这些用户发送最高投票的帖子通知。然后,我在我的Redis缓存中保存一个哈希集,将user_id映射到time_notification_recieved,自动过期时间设置为大约12小时。对于每个后续查询,我首先检查如果Redis中存在user_id,则不发送给该用户,否则发送并将id添加到Redis

这样,我就可以有一个窗口,如果用户在通知发送后突然登录或直接在应用程序上进行大量交互(改变他们的活动time),他们最多会在12小时后收到通知,但通常情况下,由于他们的活动窗口不会有太大变化,通知将每隔大约24小时(每天)发送一次。例如,与他们的time窗口为下午2点,然后在我发送通知后立即更新为下午4点,并在2小时后再次收到通知。

备注

这种方法高效吗?我最初考虑使用我的Postgres数据库来存储所有这些ID,但发现这可能会很快使数据库不堪重负。

此外,Redis适合这种情况吗?我是否可以采取完全不同的方法来实现这一点?

谢谢!

英文:

Context

I have a bunch of posts, each with upvote and downvote counts stored in my Postgres database. I am running a Gin Golang server, Flutter mobile app, and am using FCM (Firebase Cloud Messaging) to deliver notifications to users.

Architecture problem

First, the problem is solvable quite easily. I'm just unaware of how to solve it efficiently.

I want to send every user the highest voted post roughly once a day. However, I want to send the notification to users based upon when they are most active in the app (not all at once, i.e., not just 12AM daily).

So, let's say I keep track in a table called active_times an entry for each user that has a field I update based on when they interact with the mobile app like time in Postgres. I keep this updated based on user activity.

My intuition says I should have a cron job running in my server every ~2 hours which queries for all users who have their time field within that ~2 hours window. Then, I send the top post notification to these users. Then, I save in my Redis cache a hashset mapping user_ids to time_notification_recieveds, with auto-expiry set to about 12 hours. Where for every subsequent query, I first check if user_id in Redis, don't send to this user, else, do send and add the id to Redis.

This would allow me to have a window where if the user suddenly logs in or interacts a bunch on the app directly after a notification is sent to them (shifting their activity time), they'll at worst receive a notification 12 hours later, but usually since their active-window will not change much, it'll send roughly every 24 hours (daily). For example, this is opposed to their time window being 2pm and then right after I send them a notification it updates to 4pm and they get hit again in 2 hours.

Remarks

Is this an efficient way of doing it? I originally thought of using my Postgres database to store all these IDs, but figured that could really quickly overwhelm the database.

Moreover, is Redis meant for this sort of thing? Is there a completely different approach I could take to doing this?

Thanks!

答案1

得分: 1

直到你有数百万用户,那么你每隔几个小时执行的任何操作都足够高效。

我会在用户表中添加一个单独的列(例如)来记录“下一次通知时间”,以便安排通知。我想你不希望用户在使用系统后立即收到通知,对吗?

为了确定何时发送通知,你可以创建一个包含活动的小直方图的表,例如:

  • 用户ID
  • 小时
  • 计数器

每当用户进行“活动”时,就增加计数器。然后在计算“下一次发送通知的时间”时,你可以查找这个表,找到适合该特定用户的最佳时间。随着时间的推移,你可以改进算法,使其比简单的活动计数更加复杂。(也许你希望在用户通常活跃的一个小时之前发送通知?或者在他们有时使用应用程序但不是习惯性使用的时间发送通知等等)。

英文:

Until you have many millions of users then just about anything you only do every few hours will be plenty efficient.

I'd have a separate column in the users table (for example) with "next notification time" for scheduling the notifications. I imagine you don't want a scenario where a user is using the system and then immediately after gets a notification, right?

For figuring out when to send the notifications you could have a table with a mini-histogram of activity; something like

  • user_id
  • hour-of-day
  • counter

and then whenever the user does "activity" then increment the counter. Then when calculating "next time to send a notification" you look in this table to find the best hour for this particular user. Over time you could improve the algorithm to be more sophisticated than just a count of activity. (Maybe you want the notification an hour before the user is usually active? Or maybe a time when they sometimes use the app, but not as habitually, etc).

huangapple
  • 本文由 发表于 2023年7月16日 13:41:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76696851.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定