2012-03-16 96 views
157

我正在爲我們的頁面(社交遊戲類型)構建Facebook樣式通知系統,現在我正在研究設計此類系統的最佳方式。我對如何將通知推送給用戶或類似的東西不感興趣(現在甚至是)。我正在研究如何在服務器上構建系統(如何存儲通知,如何存儲它們,如何獲取它們等)。構建通知系統

所以......一些要求,我們有:

  • 在高峯時期,我們有1K左右同時登錄用戶(以及更多的客人,但他們不事這裏他們不會有通知)會產生很多事件
  • 會有不同類型的通知(用戶A已將您添加爲朋友,用戶B已對您的個人資料發表了評論,用戶C已經喜歡您的圖片,用戶D已經在遊戲X中擊敗了您,...)
  • 大多數事件會爲1個用戶生成1個通知(用戶X已經喜歡您的圖片),但會出現一種情況t會生成很多通知(例如用戶Y的生日)
  • 通知應該組合在一起;如果例如四個不同的用戶喜歡一些圖像,該圖像的所有者應該得到一個通知,指出四個用戶都喜歡的形象,而不是四個單獨的通知(就像FB一樣)

行,所以我在想什麼我應該創建一些隊列,以便在事件發生時存儲事件。然後我會有一個後臺作業(gearman?),它會查看該隊列並根據這些事件生成通知。這項工作然後將通知存儲在每個用戶的數據庫中(所以如果一個事件影響10個用戶,將會有10個單獨的通知)。然後,當用戶打開一個包含通知列表的頁面時,我會閱讀所有這些通知(我們希望限制爲100個最新通知)並將它們組合在一起,然後顯示出來。

事情我很擔心這種做法:

  • 複雜的地獄:)
  • 在數據庫這裏最好的存儲(我們正在使用MySQL),或者我應該用別的東西(Redis的好像也很適合)
  • 我應該存儲什麼作爲通知?用戶ID,發起事件的用戶ID,事件類型(以便我可以將它們分組並顯示適當的文本),但是我有點不知道如何存儲通知的實際數據(例如URL &標題被喜歡的圖像)。我應該在生成通知時「烘焙」該信息,還是應該存儲受影響的記錄(圖像,配置文件等)的ID,並在顯示通知時將信息從數據庫中拉出。
  • 即使我在顯示通知頁面時不得不處理100個通知,在這裏性能仍然可以正常運行
  • 每個請求可能存在性能問題,因爲我必須向用戶顯示未讀通知的數量(這可能是一個問題,因爲我會將通知分組在一起)。這可以避免,雖然如果我在後臺生成通知視圖(在何處分組),而不是即時的

因此,您如何看待我提出的解決方案和我的擔憂?如果您認爲我應該提及其他與此相關的內容,請發表評論。

哦,我們在頁面上使用PHP,但這不應該是我認爲的一個重要因素。

+0

需要多少時間才能將此通知系統作爲一個人的努力來完成。我只是想估計一下相應的時間表。 – Shaharyar 2015-11-24 10:55:36

+0

@Shaharyar我認爲這取決於通知系統的複雜性。 – tyan 2016-04-20 06:43:32

+0

我使用與MySQL相同的系統來構建基於優先級的通知系統。好的是,它可以擴展到幾千個用戶,如果超過這個數字,它會爆炸,特別是Android和GCM。我想知道MySQL的替代品,比如redis,rabbitMQ,Kafka,它們自然地展現了一個消息隊列,一種功能。 – 2017-01-23 13:57:33

回答

154

通知是關於某人(對象=事件,友誼..)被某人(演員)改變(動詞=添加,請求..)並報告給用戶(主題)。這是一個規範化的數據結構(儘管我已經使用了MongoDB)。您需要通知某些用戶有關更改。所以它是每個用戶的通知..這意味着如果有100個用戶參與,你會生成100個通知。

╔═════════════╗  ╔═══════════════════╗  ╔════════════════════╗ 
║notification ║  ║notification_object║  ║notification_change ║ 
╟─────────────╢  ╟───────────────────╢  ╟────────────────────╢ 
║ID   ║—1:n—→║ID     ║—1:n—→║ID     ║ 
║userID  ║  ║notificationID  ║  ║notificationObjectID║ 
╚═════════════╝  ║object    ║  ║verb    ║ 
        ╚═══════════════════╝  ║actor    ║ 
               ╚════════════════════╝ 

(添加在您認爲合適的時間字段)

這基本上是爲每個分組對象的更改,這樣你就可以說:「你有3個好友請求」。每個演員的分組是有用的,所以你可以說「用戶詹姆斯邦德在你的牀上做出了改變」。這也可以根據需要翻譯和計算通知。

但是,由於對象只是一個ID,所以需要使用單獨的調用來獲取關於所需對象的所有額外信息,除非對象實際發生更改並且要顯示該歷史記錄(例如「用戶更改了事件標題...「)

由於通知對於網站用戶來說接近實時,所以我會將它們與nodejs + websockets客戶端綁定,並將php更新添加到所有偵聽器的nod​​ejs中,以便添加更改。

+0

+1 @Artjom,這是一篇很棒的文章。我想知道,你提到'object'只是一個id。你怎麼知道它是什麼類型的對象?例如,它可能是朋友請求或其他任何內容,那麼如何將通知與適當的事件相關聯?非常感謝 – Mick 2013-04-29 01:14:57

+1

notification_object.object標識更改類型,就像字符串「友誼」 我對其更多數據的改變對象的實際引用在notification_change.notificationObjectID – 2013-04-29 07:35:41

+0

我明白了,這非常聰明。那麼,你是否需要將對象的類存儲在數據庫中的任何地方呢?或者你有沒有從存儲在'notification_object.object'中的字符串(如'friendship')檢索類的方法?因爲如果我們希望獲得關於通知對象的一些信息,我們需要使用它的類和它的標識符來加載它。我對嗎?你有這個技巧嗎?像一個事件監聽器,或將'notification_object.object'及其標識符轉換爲實際對象的東西?非常感謝@Artjom,這是巨大的幫助:) – Mick 2013-04-29 08:45:36

21

這實在是一個抽象的問題,所以我想我們只需要討論它,而不是指出你應該做什麼或不應該做什麼。

這就是我想你的顧慮:

  • 是,通知系統是複雜的,但不是地獄,但。在建模和實現這些系統時可以有多種不同的方法,並且可以具有從中等到高級的複雜性;

  • Pesonally,我總是試圖使東西數據庫驅動。爲什麼?因爲我可以保證對所發生的一切有完全的控制 - 但那只是我自己,你可以在沒有數據庫驅動的方法的情況下進行控制;相信我,你會想要控制這種情況;

  • 讓我舉例說明一個真實的案例給你,這樣你就可以從某個地方開始。在過去的一年中,我已經在某種社交網絡中建立並實施了一個通知系統(當然不是臉譜網)。我用來在那裏存儲通知的方式?我有一個notifications表,其中我保留了generator_user_id(生成通知的用戶的ID),target_user_id(很明顯,是不是?),notification_type_id(引用具有通知類型的不同表)以及我們需要的所有必要的東西來填充我們的表格(時間戳,標誌等)。我的notification_types表用於與notification_templates表關聯,該表爲每種類型的通知存儲特定模板。例如,我有一個POST_REPLY類型,它的模板類型如{USER} HAS REPLIED ONE OF YOUR #POSTS。從那裏,我只是將{}作爲變量,將#作爲參考鏈接;

  • 是的,性能應該必須沒問題。當你想到通知時,你會想到服務器從頭到腳的推動。要麼你打算用ajax請求做什麼,你都必須擔心性能。但我認爲這是第二次關注。

我設計的模型當然不是唯一可以遵循的模型,也不是最好的模型。我希望我的回答至少能讓你走向正確的方向。

+0

爲什麼我不能控制其他數據存儲? – 2012-03-16 11:40:26

+0

嗯,我沒有這麼說。我說的是我只能用數據庫驅動的方法保證數據控制;但那只是我。我要重述那個。 – 2012-03-16 11:44:28

+0

@DanielRibeiro通知模板中的佔位符({...})需要替換數據庫中不同類型通知的不同表集合中佔位符的數據。例如。一個模板是「{user}喜歡你的照片」,另一個模板是「你的{Pagename}有新的樣子。」等{PageName}和{用戶}和其他佔位符將從不同的數據庫表映射,那麼動態獲取佔位符值的模式應該是什麼。 – 2017-03-27 14:43:32

7
╔════════════════════╗ 
║notification  ║ 
╟────────────────────╢ 
║Username   ║ 
║Object    ║ 
║verb    ║ 
║actor    ║ 
║isRead    ║ 
╚════════════════════╝ 

這看起來是一個很好的答案,而不是2個集合。你可以通過用戶名,對象和isRead查詢獲得新的事件(如3個待處理的朋友請求,4個問題等等)。

讓我知道這個模式是否有問題。

+2

最常見的答案是使用規範化的數據結構,這意味着表中沒有冗餘。你的答案是否這樣做? – 2014-10-08 13:52:06