สรุป : สำหรับผู้ใช้ที่ใช้งานอยู่ประมาณ 1 ล้านคนและกิจกรรมที่เก็บไว้ 150 ล้านฉันทำให้มันง่าย:
- ใช้ฐานข้อมูลเชิงสัมพันธ์สำหรับจัดเก็บกิจกรรมที่ไม่ซ้ำกัน (1 บันทึกต่อกิจกรรม / "สิ่งที่เกิดขึ้น") สร้างระเบียนให้มีขนาดกะทัดรัดที่สุดเท่าที่จะทำได้ โครงสร้างเพื่อให้คุณสามารถคว้าชุดกิจกรรมได้อย่างรวดเร็วโดยใช้รหัสกิจกรรมหรือโดยใช้ชุดรหัสเพื่อนที่มีข้อ จำกัด ด้านเวลา
- เผยแพร่ ID กิจกรรมไปยัง Redis เมื่อใดก็ตามที่มีการสร้างบันทึกกิจกรรมเพิ่ม ID ลงในรายการ "สตรีมกิจกรรม" สำหรับผู้ใช้ทุกคนที่เป็นเพื่อน / สมาชิกที่ควรเห็นกิจกรรม
Query Redis เพื่อรับสตรีมกิจกรรมสำหรับผู้ใช้ใด ๆ แล้วหยิบข้อมูลที่เกี่ยวข้องจาก db ตามต้องการ ย้อนกลับไปยังการค้นหา db ตามเวลาถ้าผู้ใช้ต้องการเรียกดูย้อนเวลากลับไป (ถ้าคุณเสนอสิ่งนี้ด้วย)
ฉันใช้ตาราง MySQL แบบธรรมดาสำหรับจัดการกับกิจกรรมประมาณ 15 ล้านรายการ
ดูเหมือนว่า:
id
user_id (int)
activity_type (tinyint)
source_id (int)
parent_id (int)
parent_type (tinyint)
time (datetime but a smaller type like int would be better)
activity_type
บอกประเภทของกิจกรรมsource_id
บอกระเบียนที่กิจกรรมนั้นเกี่ยวข้อง ดังนั้นหากประเภทกิจกรรมหมายถึง "เพิ่มรายการโปรด" ฉันรู้ว่า source_id อ้างถึง ID ของบันทึกรายการโปรด
parent_id
/ parent_type
มีประโยชน์สำหรับ app ของฉัน - พวกเขาบอกฉันว่ากิจกรรมที่เกี่ยวข้องกับ หากหนังสือเล่มนี้เป็นที่ชื่นชอบแล้ว parent_id / parent_type จะบอกฉันว่ากิจกรรมเกี่ยวข้องกับหนังสือ (ประเภท) ด้วยคีย์หลักที่กำหนด (id)
ดัชนีฉันบนและแบบสอบถามสำหรับกิจกรรมที่เป็น(user_id, time)
user_id IN (...friends...) AND time > some-cutoff-point
การใช้ ID และการเลือกดัชนีกลุ่มอื่นอาจเป็นความคิดที่ดี - ฉันไม่ได้ทดลองสิ่งนั้น
แต่มันใช้งานได้ง่ายและใช้งานง่ายเมื่อความต้องการของคุณเปลี่ยนไป นอกจากนี้หากคุณไม่ได้ใช้ MySQL คุณอาจทำดัชนีได้ดีกว่า
สำหรับการเข้าถึงได้เร็วขึ้นเพื่อกิจกรรมล่าสุดที่ฉันได้รับการทดสอบด้วยRedis Redis เก็บข้อมูลทั้งหมดไว้ในหน่วยความจำดังนั้นคุณจึงไม่สามารถใส่กิจกรรมทั้งหมดไว้ในนั้นได้ แต่คุณสามารถจัดเก็บได้เพียงพอสำหรับหน้าจอที่ใช้กันทั่วไปส่วนใหญ่บนไซต์ของคุณ 100 รายการล่าสุดสำหรับผู้ใช้แต่ละรายหรือบางอย่างเช่นนั้น ด้วย Redis ในการผสมมันอาจทำงานเช่นนี้:
- สร้างกิจกรรม MySQL ของคุณ
- สำหรับเพื่อนแต่ละคนของผู้ใช้ที่สร้างกิจกรรมให้กด ID ลงในรายการกิจกรรมของพวกเขาใน Redis
- ตัดแต่ละรายการเป็นรายการ X สุดท้าย
Redis นั้นเร็วและเสนอวิธีในการส่งคำสั่งไปยังการเชื่อมต่อเดียวดังนั้นการผลักกิจกรรมออกไปให้เพื่อน 1,000 คนใช้เวลามิลลิวินาที
สำหรับคำอธิบายโดยละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่ฉันกำลังพูดถึงดูตัวอย่าง Twitter ของ Redis: http://redis.io/topics/twitter-clone
อัปเดตกุมภาพันธ์ 2554ฉันมีกิจกรรมที่ใช้งานอยู่ 50 ล้านรายการในขณะนี้และฉันไม่ได้เปลี่ยนแปลงอะไรเลย สิ่งหนึ่งที่ดีเกี่ยวกับการทำสิ่งที่คล้ายกันคือมันใช้แถวกะทัดรัดและเล็ก ฉันกำลังวางแผนที่จะทำการเปลี่ยนแปลงบางอย่างที่จะเกี่ยวข้องกับกิจกรรมอื่น ๆ อีกมากมายและสอบถามเพิ่มเติมเกี่ยวกับกิจกรรมเหล่านั้นและฉันจะใช้ Redis เพื่อให้สิ่งต่าง ๆ รวดเร็ว ฉันใช้ Redis ในด้านอื่น ๆ และมันใช้ได้ดีกับปัญหาบางประเภท
อัปเดตกรกฎาคม 2014เรามีผู้ใช้งานรายเดือนประมาณ 700,000 ราย ในช่วงสองสามปีที่ผ่านมาฉันใช้ Redis (ดังอธิบายไว้ในรายการหัวข้อย่อย) สำหรับการจัดเก็บ 1,000 ID กิจกรรมล่าสุดสำหรับผู้ใช้แต่ละคน โดยปกติจะมีบันทึกกิจกรรมประมาณ 100 ล้านรายการในระบบและยังคงเก็บไว้ใน MySQL และยังคงเป็นเค้าโครงเดียวกัน บันทึกเหล่านี้ช่วยให้เราได้รับหน่วยความจำ Redis น้อยลงซึ่งทำหน้าที่เป็นบันทึกข้อมูลกิจกรรมและเราใช้ข้อมูลเหล่านั้นหากผู้ใช้ต้องการย้อนเวลากลับไปเพื่อค้นหาบางสิ่งเพิ่มเติม
นี่ไม่ใช่ทางออกที่ฉลาดหรือน่าสนใจโดยเฉพาะ แต่มันให้บริการฉันดี