สร้างระบบการแจ้งเตือน [ปิด]


170

ฉันกำลังเริ่มสร้างระบบแจ้งเตือนสไตล์ Facebook สำหรับหน้าของเรา (ประเภทเกมโซเชียล) และตอนนี้ฉันกำลังค้นคว้าว่าอะไรจะเป็นวิธีที่ดีที่สุดในการออกแบบระบบดังกล่าว ฉันไม่สนใจที่จะส่งการแจ้งเตือนไปยังผู้ใช้หรืออะไรทำนองนั้น (ตอนนี้ยัง) ฉันกำลังค้นคว้าวิธีการสร้างระบบบนเซิร์ฟเวอร์ (วิธีจัดเก็บการแจ้งเตือนตำแหน่งที่จะจัดเก็บพวกเขาวิธีการดึงข้อมูลพวกเขา ฯลฯ ... )

ดังนั้น ... ข้อกำหนดบางประการที่เรามี:

  • ในช่วงเวลาเร่งด่วนเรามีผู้ใช้ที่เข้าสู่ระบบพร้อมกันประมาณ 1k (และแขกอีกหลายคน แต่พวกเขาไม่สำคัญที่นี่เพราะพวกเขาจะไม่มีการแจ้งเตือน) ที่จะสร้างกิจกรรมมากมาย
  • จะมีการแจ้งเตือนประเภทต่างๆ (ผู้ใช้ A เพิ่มคุณเป็นเพื่อนผู้ใช้ B ได้แสดงความคิดเห็นในโปรไฟล์ของคุณผู้ใช้ C ชอบรูปของคุณผู้ใช้ D ทำให้คุณชนะในเกม X, ... )
  • กิจกรรมส่วนใหญ่จะสร้างการแจ้งเตือน 1 รายการสำหรับผู้ใช้ 1 ราย (ผู้ใช้ X ชอบรูปของคุณ) แต่จะมีบางกรณีที่เหตุการณ์หนึ่งเหตุการณ์จะสร้างการแจ้งเตือนจำนวนมาก (เช่นวันเกิดของผู้ใช้ Y เป็นต้น)
  • ควรจัดกลุ่มการแจ้งเตือนด้วยกัน ถ้าเช่นผู้ใช้สี่คนที่แตกต่างกันเช่นภาพบางภาพเจ้าของควรได้รับการแจ้งเตือนหนึ่งรายการซึ่งระบุว่าผู้ใช้สี่คนชอบภาพและไม่ใช่การแจ้งเตือนสี่แยกต่างหาก (เช่นเดียวกับ FB)

ตกลงดังนั้นสิ่งที่ฉันคิดคือฉันควรสร้างคิวบางประเภทที่ฉันจะเก็บเหตุการณ์เมื่อเกิดขึ้น จากนั้นฉันจะมีงานพื้นหลัง ( Gearman ?) ที่จะดูคิวนั้นและสร้างการแจ้งเตือนตามเหตุการณ์เหล่านั้น งานนี้จะจัดเก็บการแจ้งเตือนในฐานข้อมูลสำหรับผู้ใช้แต่ละคน (ดังนั้นหากเหตุการณ์มีผลกระทบต่อผู้ใช้ 10 คนจะมีการแจ้งเตือนแยกต่างหาก 10 รายการ) จากนั้นเมื่อผู้ใช้เปิดหน้ารายการการแจ้งเตือนฉันจะอ่านการแจ้งเตือนทั้งหมดสำหรับเขา (เราหวังว่าจะ จำกัด การแจ้งเตือนล่าสุดนี้ไว้ที่ 100 การแจ้งเตือนล่าสุด) และจัดกลุ่มการแจ้งเตือนเหล่านั้นเข้าด้วยกัน

สิ่งที่ฉันกังวลเกี่ยวกับวิธีการนี้:

  • ซับซ้อนเหมือนนรก :)
  • เป็นฐานข้อมูลที่เก็บข้อมูลที่ดีที่สุดที่นี่ (เราใช้ MySQL) หรือฉันควรใช้อย่างอื่น (สีแดงดูเหมือนว่าจะพอดีดีเกินไป)
  • ฉันควรเก็บสิ่งใดไว้เป็นการแจ้งเตือน ID ผู้ใช้ ID ผู้ใช้ที่เริ่มต้นเหตุการณ์ประเภทของเหตุการณ์ (เพื่อให้ฉันสามารถจัดกลุ่มพวกเขาและแสดงข้อความที่เหมาะสม) แต่แล้วฉันก็ไม่รู้วิธีการจัดเก็บข้อมูลที่แท้จริงของการแจ้งเตือน (เช่น URL และชื่อของภาพที่ ถูกชอบ) ฉันควร "อบ" ข้อมูลนั้นเมื่อฉันสร้างการแจ้งเตือนหรือฉันควรจัดเก็บ ID ของบันทึก (รูปภาพโปรไฟล์ ... ) ได้รับผลกระทบและดึงข้อมูลออกจากฐานข้อมูลเมื่อแสดงการแจ้งเตือน
  • ประสิทธิภาพควรจะตกลงที่นี่แม้ว่าฉันจะต้องดำเนินการแจ้งเตือน 100 รายการแบบทันทีขณะแสดงหน้าการแจ้งเตือน
  • ปัญหาประสิทธิภาพที่เป็นไปได้ในทุกคำขอเพราะฉันจะต้องแสดงจำนวนการแจ้งเตือนที่ยังไม่ได้อ่านให้กับผู้ใช้ (ซึ่งอาจเป็นปัญหาในตัวเองตั้งแต่ฉันจะจัดกลุ่มการแจ้งเตือนด้วยกัน) สิ่งนี้สามารถหลีกเลี่ยงได้หากฉันสร้างมุมมองการแจ้งเตือน (ซึ่งจัดกลุ่มไว้) ในพื้นหลังและไม่ใช่แบบทันที

แล้วคุณคิดอย่างไรเกี่ยวกับวิธีแก้ไขปัญหาที่เสนอและข้อกังวลของฉัน โปรดแสดงความคิดเห็นหากคุณคิดว่าฉันควรพูดถึงสิ่งอื่นที่จะเกี่ยวข้องที่นี่

โอ้เรากำลังใช้ PHP สำหรับหน้าของเรา แต่นั่นไม่ควรเป็นปัจจัยใหญ่ที่ฉันคิด


คุณใช้เวลาสร้างระบบการแจ้งเตือนนี้เท่าไร ฉันแค่อยากจะมีการประมาณค่าเพื่อทำให้เส้นเวลาเป็นไปตามนั้น
Shaharyar

@Shaharyar ฉันคิดว่ามันขึ้นอยู่กับความซับซ้อนของระบบการแจ้งเตือน
tyan

ฉันใช้ระบบเดียวกันกับ MySQL เพื่อสร้างระบบการแจ้งเตือนตามลำดับความสำคัญ สิ่งที่ดีคือมันขยายไปถึงผู้ใช้เพียงไม่กี่พันคนถ้ามันมากกว่านั้นมันจะระเบิดโดยเฉพาะกับ Android และ GCM ฉันต้องการทราบทางเลือกอื่น ๆ ของ MySQL เช่น redis, rabbitMQ, Kafka ซึ่งแสดงคิวข้อความชนิดของการทำงาน
Ankit Marothi

คำตอบ:


168

การแจ้งเตือนเกี่ยวกับบางสิ่งบางอย่าง (object = event, มิตรภาพ .. ) กำลังถูกเปลี่ยนแปลง (กริยา = เพิ่ม, ขอ .. ) โดยบางคน (นักแสดง) และรายงานต่อผู้ใช้ (เรื่อง) นี่คือโครงสร้างข้อมูลปกติ (แม้ว่าฉันจะใช้ 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 ผลักดันการปรับปรุงเพื่อ nodejs สำหรับผู้ฟังทั้งหมดเมื่อการเปลี่ยนแปลงได้รับการเพิ่ม


1
notification_object.object ชนิดระบุการเปลี่ยนแปลงเช่นสตริง "มิตรภาพ" การอ้างอิงที่เกิดขึ้นจริงกับวัตถุที่มีการเปลี่ยนแปลงที่มีข้อมูลพิเศษที่ฉันพูดคุยเกี่ยวกับการอยู่ใน notification_change.notificationObjectID
Artjom Kurapov

2
นี่อาจเป็นคำถามที่โง่ แต่ด้วยการตั้งค่านี้คุณจะทำอย่างไรเมื่อผู้ใช้เห็นหรือทำตามการแจ้งเตือน คุณเพิ่งลบออกจากฐานข้อมูลหรือเพียงแค่ใช้วันที่เพื่อดูว่าผู้ใช้เข้าสู่ระบบตั้งแต่การแจ้งเตือนถูกสร้างขึ้น?
Jeffery Mills

4
ฉันรู้ว่าหัวข้อนี้ค่อนข้างเก่าอยู่แล้ว แต่ฉันค่อนข้างงงกับตารางแรกอะไรคือจุดประสงค์ของตารางนี้อย่างยอดเยี่ยม อะไรคือข้อดีของการมีสิ่งนี้เป็นตารางที่แยกต่างหากเมื่อเทียบกับการใส่ userID ในตาราง notification_object กล่าวอีกนัยหนึ่งเมื่อคุณจะสร้างรายการใหม่ในการแจ้งเตือนและเมื่อใดคุณจะเพิ่มวัตถุและเปลี่ยนเป็นการแจ้งเตือนที่มีอยู่ด้วยโครงสร้างนี้
Bas Goossen

3
@JefferyMills คุณอาจมีข้อมูลสถานะเช่นis_notification_readในnotificationตารางและทำเครื่องหมายได้อย่างเหมาะสมถ้ามันเป็นunread, หรือread deleted
Kevin

2
ฉันพยายามดิ้นรนที่จะเข้าใจบางแง่มุมของการแก้ปัญหานี้และสร้างคำถามแยกต่างหากเกี่ยวกับมัน: dba.stackexchange.com/questions/99401/…
45623

27

นี่เป็นคำถามที่เป็นนามธรรมจริงๆดังนั้นฉันคิดว่าเราแค่ต้องพูดคุยแทนที่จะชี้ให้เห็นว่าคุณควรทำหรือไม่ควรทำ

นี่คือสิ่งที่ฉันคิดเกี่ยวกับความกังวลของคุณ:

  • ใช่ระบบการแจ้งเตือนมีความซับซ้อน แต่ไม่เหมือนนรก คุณสามารถมีวิธีที่แตกต่างมากมายในการสร้างแบบจำลองและการนำระบบดังกล่าวมาใช้และพวกเขาสามารถมีได้ตั้งแต่ระดับกลางจนถึงระดับสูงของความซับซ้อน

  • ผมพยายามทำให้ทุกอย่างเป็นฐานข้อมูล ทำไม? เนื่องจากฉันสามารถรับประกันได้ว่าจะมีการควบคุมทุกอย่างที่เกิดขึ้น - แต่นั่นเป็นเพียงฉันเท่านั้นคุณสามารถควบคุมได้โดยไม่ต้องใช้วิธีการที่ใช้ฐานข้อมูล เชื่อฉันสิคุณจะต้องควบคุมในกรณีนั้น

  • ฉันขอยกตัวอย่างกรณีจริงให้คุณเพื่อให้คุณสามารถเริ่มจากที่ไหนสักแห่ง ในปีที่ผ่านมาฉันสร้างแบบจำลองและใช้ระบบแจ้งเตือนในเครือข่ายสังคมออนไลน์บางประเภท (ไม่เหมือน Facebook แน่นอน) วิธีที่ฉันใช้ในการจัดเก็บการแจ้งเตือนที่นั่น? ฉันมีnotificationsตารางที่ฉันเก็บไว้generator_user_id(ID ของผู้ใช้ที่สร้างการแจ้งเตือน), target_user_id(ชนิดที่เห็นได้ชัดใช่มั้ย), notification_type_id(ที่อ้างถึงตารางอื่นที่มีประเภทการแจ้งเตือน) และทั้งหมด สิ่งที่จำเป็นที่เราต้องกรอกตารางของเราด้วย (การประทับเวลา, ธง, ฯลฯ ) notification_typesตารางของฉันเคยมีความสัมพันธ์กับnotification_templatesตารางซึ่งเก็บแม่แบบเฉพาะไว้สำหรับการแจ้งเตือนแต่ละประเภท ยกตัวอย่างเช่นผมมีชนิดที่มีแม่แบบชนิดเช่นPOST_REPLY {USER} HAS REPLIED ONE OF YOUR #POSTSจากตรงนั้นฉันเพิ่งปฏิบัติต่อ{}เป็นตัวแปรและ#ลิงก์อ้างอิง

  • ใช่ประสิทธิภาพควรและจะต้องตกลง เมื่อคุณคิดถึงการแจ้งเตือนคุณนึกถึงการที่เซิร์ฟเวอร์ผลักจากหัวจรดเท้า ไม่ว่าคุณจะทำอะไรกับคำขออาแจ็กซ์หรืออะไรก็ตามคุณจะต้องกังวลเกี่ยวกับประสิทธิภาพ แต่ฉันคิดว่านั่นเป็นครั้งที่สองที่กังวล

แน่นอนว่าแบบจำลองที่ฉันออกแบบนั้นไม่ใช่แบบเดียวที่คุณสามารถติดตามได้ ฉันหวังว่าคำตอบของฉันอย่างน้อยก็ติดตามคุณไปในทิศทางที่ถูกต้อง


เหตุใดฉันจึงไม่สามารถควบคุมกับแหล่งข้อมูลอื่นได้
Jan Hančič

ฉันไม่ได้พูดอย่างนั้น สิ่งที่ฉันพูดคือฉันสามารถรับประกันการควบคุมข้อมูลด้วยวิธีการที่ใช้ฐานข้อมูลเท่านั้น แต่นั่นเป็นเพียงฉัน ฉันจะเรียบเรียงใหม่อีกครั้ง
Daniel Ribeiro

@DanielRibeiro ตัวยึดตำแหน่ง ({... }) ในแม่แบบการแจ้งเตือนจำเป็นต้องแทนที่ข้อมูลของตัวยึดตำแหน่งจากชุดตารางที่แตกต่างกันในฐานข้อมูลสำหรับประเภทการแจ้งเตือนที่แตกต่างกัน เช่นหนึ่งเทมเพลตคือ "{user} ชอบรูปถ่ายของคุณ" และอีกหนึ่งเทมเพลตคือ "{Pagename} ของคุณมีรูปแบบใหม่" อื่น ๆ {PageName} และ {user} และตัวยึดตำแหน่งอื่นจะแมปจากตารางฐานข้อมูลที่แตกต่างกันดังนั้นสกีมาที่ควรได้รับค่าตัวยึดตำแหน่งแบบไดนามิกคืออะไร
Ashish Shukla

DanielRibeiro วิธีที่คุณแทนที่ตัวยึดตำแหน่งที่ถูกถามโดย @Ashish Shukla
Shantaram Tupe

@AishishShukla คุณใช้หรือแทนที่ตัวยึดแล้วหรือยัง
Shantaram Tupe

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

นี่เป็นคำตอบที่ดีแทนที่จะมี 2 คอลเล็กชัน คุณสามารถค้นหาด้วยชื่อผู้ใช้วัตถุและ isRead เพื่อรับกิจกรรมใหม่ (เช่นคำขอเป็นเพื่อน 3 คำขอรอคำถาม 4 คำถามถาม ฯลฯ ... )

แจ้งให้เราทราบหากมีปัญหากับสคีมานี้


3
คำตอบยอดนิยมใช้โครงสร้างข้อมูลปกติซึ่งหมายความว่าไม่มีความซ้ำซ้อนในตาราง คำตอบของคุณทำอย่างนั้น?
Aaron Hall

4

โดยส่วนตัวฉันไม่เข้าใจไดอะแกรมสำหรับคำตอบที่ยอมรับได้ดีดังนั้นฉันจะแนบไดอะแกรมฐานข้อมูลกับสิ่งที่ฉันสามารถเรียนรู้จากคำตอบที่ยอมรับและหน้าอื่น ๆ

ป้อนคำอธิบายรูปภาพที่นี่

ได้รับการปรับปรุงเป็นอย่างดี


ดูเหมือนว่า message_template จะอยู่ในตาราง NotificationType ดูเหมือนว่า main_url จะอยู่ในตารางการแจ้งเตือนจากนั้นคุณสามารถกำจัดตาราง Notification_Message ได้ คุณสามารถอธิบายเหตุผลที่คุณมีตาราง NotificationMessage ด้วยตนเองได้หรือไม่
เจฟฟ์ไรอัน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.