Bir bildirim sistemi oluşturma [kapalı]


170

Sayfamız için bir Facebook tarzı bildirim sistemi oluşturmaya başlıyorum (sosyal oyun türü) ve şimdi böyle bir sistemi tasarlamanın en iyi yolunun ne olacağını araştırıyorum. Kullanıcıya veya bunun gibi bir şeye bildirimlerin nasıl gönderileceği ile ilgilenmiyorum (şimdilik). Sistemi sunucuda nasıl oluşturacağımı araştırıyorum (bildirimleri nasıl saklayacağımı, nerede saklayacağımı, nasıl getireceğimizi vb.).

Yani ... sahip olduğumuz bazı gereksinimler:

  • en yoğun zamanlarda yaklaşık 1 bin eşzamanlı giriş yapan kullanıcımız var (ve daha birçok misafir var, ancak bildirimde bulunmayacakları için burada önemli değiller)
  • farklı bildirim türleri olacaktır (A kullanıcısı sizi arkadaş olarak ekledi, B kullanıcısı profilinize yorum yaptı, C kullanıcısı resminizi beğendi, D kullanıcısı X oyununda sizi dövdü ...)
  • çoğu etkinlik 1 kullanıcı için 1 bildirim oluşturur (X kullanıcısı resminizi beğendi), ancak bir etkinliğin çok sayıda bildirim üreteceği durumlar olacaktır (örneğin, kullanıcının Y'nin doğum günüdür)
  • bildirimler birlikte gruplandırılmalıdır; örneğin, bir görüntüyü beğenen dört farklı kullanıcı varsa, bu görüntünün sahibi dört kullanıcının değil, dört kullanıcının görüntüyü sevdiğini belirten bir bildirim almalıdır (tıpkı FB'nin yaptığı gibi)

Tamam, düşündüğüm şey, olayları gerçekleştiğinde depolayacağım bir tür kuyruk oluşturmam gerektiğidir. Sonra bu kuyruğa bakmak ve bu olaylara dayalı bildirimler oluşturmak bir arka plan işi ( dişli ?) Olurdu . Bu iş daha sonra her kullanıcı için bildirimleri veritabanında depolar (bu nedenle bir olay 10 kullanıcıyı etkiliyorsa, 10 ayrı bildirim olacaktır). Daha sonra kullanıcı bildirimler listesiyle bir sayfa açtığında onun için tüm bu bildirimleri okurdum (bunu en son 100 bildirimle sınırlamayı düşünüyoruz) ve bunları bir araya getirip sonunda görüntüleyeceğiz.

Bu yaklaşımla ilgili endişelerim var:

  • cehennem gibi karmaşık :)
  • veritabanı burada en iyi depolama (MySQL kullanıyoruz) veya başka bir şey kullanmalıyım (redis de iyi bir uyum gibi görünüyor)
  • bildirim olarak ne saklamalıyım? kullanıcı kimliği, olayı başlatan kullanıcı kimliği, olay türü (böylece onları gruplayabilir ve uygun metni görüntüleyebilirim), ancak daha sonra bildirimin gerçek verilerini nasıl saklayacağımı bilmiyorum (örneğin URL ve resmin başlığı beğenildi). Bildirimi oluşturduğumda bu bilgiyi "pişirmem" gerekir mi yoksa etkilenen kaydın kimliğini (resim, profil, ...) saklamalı ve bildirimi görüntülerken bilgileri DB'den çıkarmam gerekir mi?
  • bildirimler sayfasını görüntülerken anında 100 bildirimi işlemek zorunda kalsam bile performansın iyi olması gerekir
  • her istekte olası performans sorunu, çünkü kullanıcıya okunmamış bildirimlerin sayısını görüntülemek zorunda kalacağım (bildirimleri birlikte gruplayacağımdan beri kendi başına bir sorun olabilir). Bildirimlerin görünümünü (gruplandırıldıkları yerde) arka planda oluşturduğum ve anında değil oluşturduysam bu önlenebilir

Peki önerilen çözümüm ve endişelerim hakkında ne düşünüyorsunuz? Burada alakalı olabilecek başka bir şeyden bahsetmem gerektiğini düşünüyorsanız lütfen yorum yapın.

Oh, sayfamız için PHP kullanıyoruz, ancak bence bu büyük bir faktör olmamalı.


Bu bildirim sistemini bir insanın çabasıyla oluşturması ne kadar zaman aldı. Sadece zaman çizelgelerini buna göre yapmak için bir tahmin yapmak istiyorum.
Shaharyar

@Shaharyar Bence bildirim sisteminin karmaşıklığına bağlı.
tyan

Öncelik tabanlı bir bildirim sistemi oluşturmak için aynı sistemi MySQL ile kullandım. İyi olan şey, birkaç bin kullanıcıya ölçeklendirilmesidir, eğer daha fazla olursa, özellikle Android ve GCM ile patlar. Doğal olarak bir mesaj kuyruğu, bir tür işlevsellik sergileyen redis, rabbitMQ, Kafka gibi MySQL'e alternatifler bilmek istiyorum.
Ankit Marothi

Yanıtlar:


168

Bildirim, birisi (aktör) tarafından değiştirilen (kullanıcı = konu) bir şeyin (nesne = olay, arkadaşlık ..) değiştirilmesiyle (fiil = eklendi, talep edildi ..) ilgilidir. İşte normalleştirilmiş bir veri yapısı (MongoDB kullandığım halde). Bazı kullanıcıları değişiklikler hakkında bilgilendirmeniz gerekir. Yani kullanıcı başına bildirimler .. yani 100 kullanıcı varsa 100 bildirim oluşturursunuz.

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

(Uygun gördüğünüz zaman alanlarını ekleyin)

Bu, temel olarak nesne başına değişiklikleri gruplandırmak içindir, böylece "3 arkadaş isteğiniz var" diyebilirsiniz. Ve oyuncu başına gruplama yararlıdır, böylece "Kullanıcı James Bond yatağınızda değişiklikler yaptı" diyebilirsiniz. Bu, bildirimleri istediğiniz gibi çevirme ve sayma olanağı da sağlar.

Ancak, nesne sadece bir kimlik olduğu için, nesne gerçekten değişmedikçe ve bu geçmişi göstermek istemediğiniz sürece, ayrı çağrılarla istediğiniz nesne hakkında tüm ekstra bilgileri almanız gerekir (örneğin, "kullanıcı etkinlik başlığını ... ")

Bildirimler sitedeki kullanıcılar için gerçek zamanlıya yakın olduğundan, değişiklik eklendiğinde onları php ile nodejs güncellemesini iten php ile nodejs + websockets istemcisi ile bağlarım.


1
message_object.object, değişiklik türünü, bir dize "dostluk" gibi tanımlar.
Konuştuğum

2
Bu aptalca bir soru olabilir, ancak bu kurulumla kullanıcı bildirimi gördükten veya harekete geçtikten sonra ne yaparsınız? Veritabanından kaldırıyor musunuz yoksa kullanıcının bildirim oluşturulduğundan beri oturum açıp açmadığını görmek için sadece tarihleri ​​mi kullanıyorsunuz?
Jeffery Mills

4
Bu konunun zaten oldukça eski olduğunu biliyorum, ancak ilk tablo hakkında biraz şaşkınım, tam olarak bu tablonun amacı nedir? Bunu userID'yi bildirim_object tablosuna koymak yerine ayrı bir tablo olarak almanın avantajı nedir? Başka bir deyişle, bildirimde ne zaman yeni bir giriş oluşturacaksınız ve bu yapı ile ne zaman bir nesne ekleyeceksiniz ve var olan bir bildirime geçeceksiniz?
Bas Goossen

3
Sen böyle bir durumu alanını olabilir @JefferyMills is_notification_readiçinde notificationmasa ve bunun ise uygun işaretlemek unread, readya deleted.
Kevin

2
Ayrıca bu çözümün bazı yönlerini anlamak için mücadele ettim ve bununla ilgili ayrı bir soru yaptım: dba.stackexchange.com/questions/99401/…
user45623

27

Bu gerçekten soyut bir soru, bu yüzden ne yapmanız ya da yapmamanız gerektiğini belirtmek yerine sadece tartışmamız gerekecek.

Endişeleriniz hakkında şöyle düşünüyorum:

  • Evet, bir bildirim sistemi karmaşıktır, ancak cehennem kadar değil. Bu tür sistemlerin modellenmesi ve uygulanması konusunda birçok farklı yaklaşımınız olabilir ve bunlar orta düzeyden yüksek düzeyde karmaşıklığa sahip olabilir;

  • Pesonally, her zaman veritabanı odaklı şeyler yapmaya çalışıyorum. Neden? Çünkü devam eden her şeyin tam kontrolünü sağlayabileceğimi garanti edebilirim - ama bu sadece benim, veritabanı odaklı bir yaklaşım olmadan kontrol sahibi olabilirsiniz; güven bana, bu durumda kontrol isteyeceksin;

  • Senin için gerçek bir örneği örnekleyeyim, böylece bir yerden başlayabilirsin. Geçen yıl bir tür sosyal ağda (facebook gibi değil, elbette) bir bildirim sistemi modelleyip uyguladım. Bildirimleri orada saklamak için kullandığım yöntem? (Bildirimi oluşturan kullanıcının kimliği), (açık bir tür değil mi?), (Bildirim türleriyle farklı bir tabloya gönderme yapan) ve tüm verileri notificationssakladığım bir tablo vardı. tablolarımızı doldurmamız gereken gerekli şeyler (zaman damgaları, bayraklar, vb.). Benim bir bir ilişki için kullanılan masa masa, her bildirim türü için depolanan spesifik şablonları. Mesela bende böyle bir şablonu olan bir tipim vardı . Oradan, ben sadece tedavigenerator_user_idtarget_user_idnotification_type_idnotification_typesnotification_templatesPOST_REPLY{USER} HAS REPLIED ONE OF YOUR #POSTS{}bir değişken ve #bir referans linki olarak;

  • Evet, performans iyi olmalı ve iyi olmalıdır . Bildirimleri düşündüğünüzde sunucuyu baştan aşağı itmeyi düşünüyorsunuz. Ya ajax istekleriyle ya da her neyse yapacaksanız, performans konusunda endişelenmeniz gerekecek. Ama bence bu ikinci bir endişe;

Tasarladığım model elbette takip edebileceğiniz tek model değil, aynı zamanda en iyisi de değil. Umarım cevabım en azından sizi doğru yönde takip eder.


Neden başka bir veri deposuyla kontrolüm olmasın?
Jan Hančič

Bunu söylemedim. Söylediğim sadece veri tabanlı bir yaklaşımla veri kontrolünü garanti edebileceğim; ama bu sadece benim. Bunu yeniden ifade edeceğim.
Daniel Ribeiro

@DanielRibeiro bildirim şablonundaki yer tutucuların ({...}), farklı türde bildirimler için veritabanındaki farklı tablo kümelerinden yer tutucuların verilerini değiştirmesi gerekir. Örneğin, bir şablon "{user} fotoğrafınızı beğendi." Vb {PageName} ve {user} ve diğer yer tutucular farklı veritabanı tablosundan eşleşecektir, bu nedenle yer tutucuların dinamik olarak değerini almak için şema ne olmalıdır?
Ashish Shukla

DanielRibeiro, @Ashish Shukla,
Shantaram

@AshishShukla yer tutucuları kullandınız veya değiştirdiniz ve nasıl?
Shantaram Tupe

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

Bu, 2 koleksiyona sahip olmak yerine iyi bir yanıt gibi görünüyor. Yeni etkinlikler almak için kullanıcı adına, nesneye ve isRead'e göre sorgulayabilirsiniz (beklemede olan 3 arkadaşlık isteği, 4 soru sorulur vb.)

Bu şema ile ilgili bir sorun olup olmadığını bana bildirin.


3
Üst yanıt normalleştirilmiş bir veri yapısı kullandı, bu da tablolarda artıklık olmadığı anlamına geliyor. Cevabınız bunu yapıyor mu?
Aaron Hall

4

Şahsen kabul edilen cevap için diyagramı çok iyi anlamıyorum, bu yüzden kabul edilen cevap ve diğer sayfalardan neler öğrenebileceğime dair bir veritabanı diyagramı ekleyeceğim.

resim açıklamasını buraya girin

Gelişmeler iyi karşılandı.


Message_template, NotificationType tablosunda olurdu. Ayrıca main_url bildirimler tablosunda olacak gibi görünüyor, o zaman Notification_Message tablosunu ortadan kaldırabilirsiniz. NotificationMessage tablonuzun kendi başına nedenini açıklayabilir misiniz?
Jeff Ryan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.