Cách triển khai luồng hoạt động trong mạng xã hội


140

Tôi đang phát triển mạng xã hội của riêng mình và tôi không tìm thấy trên các ví dụ web về việc triển khai luồng hành động của người dùng ... Ví dụ: làm thế nào để lọc hành động cho mỗi người dùng? Làm thế nào để lưu trữ các sự kiện hành động? Mô hình dữ liệu và mô hình đối tượng nào tôi có thể sử dụng cho luồng hành động và cho các hành động của nó?


9
chúc may mắn, đây là câu hỏi không bao giờ kết thúc mà tất cả chúng ta muốn biết, làm thế nào để facebook kéo nó ra, câu trả lời rất phức tạp và chúng ta có thể không bao giờ biết cách làm hiệu quả nhất. Nếu bạn tìm thấy một cách tiếp cận TỐT, vui lòng đăng nó ở đây để người khác xem, BTW điều này đã được thảo luận nhiều lần trên SO vì vậy chỉ cần tìm kiếm và bạn sẽ tìm thấy một số mẹo
JasonDavis

1
Stream Framework là giải pháp được sử dụng rộng rãi nhất: github.com/tschellenbach/Stream-Framework Cũng xem danh sách các gói này: djangopackages.com/grids/g/activities
Thierry

1
Về mặt cá nhân hóa, nó dựa trên phân tích và học máy, Ngoài ra, hãy xem getstream.io/personalization
Thierry

Câu trả lời:


241

Tóm tắt : Đối với khoảng 1 triệu người dùng hoạt động và 150 triệu hoạt động được lưu trữ, tôi giữ cho nó đơn giản:

  • Sử dụng cơ sở dữ liệu quan hệ để lưu trữ các hoạt động duy nhất (1 bản ghi cho mỗi hoạt động / "điều đã xảy ra") Làm cho các bản ghi nhỏ gọn nhất có thể. Cấu trúc để bạn có thể nhanh chóng lấy một loạt các hoạt động bằng ID hoạt động hoặc bằng cách sử dụng một bộ ID bạn bè với các ràng buộc về thời gian.
  • Xuất bản ID hoạt động lên Redis bất cứ khi nào bản ghi hoạt động được tạo, thêm ID vào danh sách "luồng hoạt động" cho mọi người dùng là bạn bè / người đăng ký sẽ thấy hoạt động.

Truy vấn Redis để lấy luồng hoạt động cho bất kỳ người dùng nào và sau đó lấy dữ liệu liên quan từ db khi cần. Quay trở lại truy vấn db theo thời gian nếu người dùng cần duyệt ngược thời gian (nếu bạn thậm chí cung cấp điều này)


Tôi sử dụng một bảng MySQL cũ đơn giản để xử lý khoảng 15 triệu hoạt động.

Nó trông giống như thế này:

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_typecho tôi biết loại hoạt động, source_idcho tôi biết hồ sơ mà hoạt động đó có liên quan. Vì vậy, nếu loại hoạt động có nghĩa là "thêm yêu thích" thì tôi biết rằng source_id đề cập đến ID của một bản ghi yêu thích.

các parent_id/parent_type rất hữu ích cho ứng dụng của tôi - họ cho tôi biết những gì hoạt động có liên quan đến. Nếu một cuốn sách được yêu thích, thì Parent_id / Parent_type sẽ cho tôi biết rằng hoạt động liên quan đến một cuốn sách (loại) với một khóa chính (id) đã cho

Tôi lập chỉ mục (user_id, time)và truy vấn cho các hoạt động được user_id IN (...friends...) AND time > some-cutoff-point. Việc bỏ id và chọn một chỉ mục cụm khác nhau có thể là một ý tưởng hay - tôi chưa thử nghiệm điều đó.

Những thứ khá cơ bản, nhưng nó hoạt động, nó đơn giản và dễ dàng làm việc khi nhu cầu của bạn thay đổi. Ngoài ra, nếu bạn không sử dụng MySQL, bạn có thể thực hiện chỉ mục tốt hơn.


Để truy cập nhanh hơn vào các hoạt động gần đây nhất, tôi đã thử nghiệm với Redis . Redis lưu trữ tất cả dữ liệu trong bộ nhớ, vì vậy bạn không thể đặt tất cả các hoạt động của mình vào đó, nhưng bạn có thể lưu trữ đủ cho hầu hết các màn hình thường gặp trên trang web của mình. 100 gần đây nhất cho mỗi người dùng hoặc một cái gì đó như thế. Với Redis trong hỗn hợp, nó có thể hoạt động như thế này:

  • Tạo hồ sơ hoạt động MySQL của bạn
  • Đối với mỗi người bạn của người dùng đã tạo hoạt động, hãy đẩy ID vào danh sách hoạt động của họ trong Redis.
  • Cắt từng danh sách cho các mục X cuối cùng

Redis rất nhanh và cung cấp một cách để truyền các lệnh trên một kết nối - vì vậy việc đẩy một hoạt động ra tới 1000 bạn bè mất một phần nghìn giây.

Để được giải thích chi tiết hơn về những gì tôi đang nói, hãy xem ví dụ Twitter của Redis: http://redis.io/topics/twitter-clone

Cập nhật tháng 2 năm 2011 Tôi có 50 triệu hoạt động tích cực vào lúc này và tôi không thay đổi gì cả. Một điều tuyệt vời khi làm một cái gì đó tương tự như thế này là nó sử dụng các hàng nhỏ gọn. Tôi đang lên kế hoạch thực hiện một số thay đổi sẽ liên quan đến nhiều hoạt động hơn và nhiều truy vấn hơn về các hoạt động đó và tôi chắc chắn sẽ sử dụng Redis để giữ mọi thứ nhanh chóng. Tôi đang sử dụng Redis trong các lĩnh vực khác và nó thực sự hoạt động tốt đối với một số loại vấn đề.

Cập nhật tháng 7 năm 2014 Chúng tôi có tới khoảng 700 nghìn người dùng hoạt động hàng tháng. Trong vài năm qua, tôi đã sử dụng Redis (như được mô tả trong danh sách gạch đầu dòng) để lưu trữ 1000 ID hoạt động cuối cùng cho mỗi người dùng. Thường có khoảng 100 triệu bản ghi hoạt động trong hệ thống và chúng vẫn được lưu trữ trong MySQL và vẫn có cùng bố cục. Những bản ghi này cho phép chúng tôi thoát khỏi bộ nhớ Redis ít hơn, chúng đóng vai trò là bản ghi dữ liệu hoạt động và chúng tôi sử dụng chúng nếu người dùng cần quay ngược thời gian để tìm thứ gì đó.

Đây không phải là một giải pháp thông minh hoặc đặc biệt thú vị nhưng nó đã phục vụ tôi rất tốt.


2
+1 cho Redis. v2 sử dụng bộ nhớ ảo nên có thể dựa hoàn toàn vào Redis
stagas

16
Nếu có nhiều nguồn hoạt động (thêm, bình luận, thích, v.v.), làm thế nào để bạn tham gia bảng này với các hoạt động thực tế? Bạn có sử dụng nhiều liên kết trái (mỗi cho một bảng hoạt động) không?
Ali Shakiba

1
@casey Echoing câu hỏi của @JohnS - làm thế nào để bạn thực hiện JOINtrên các activity_typebảng khác nhau ? Là những người tham gia hiệu suất đắt tiền khôn ngoan?
Rob Sobers

1
Có ai có câu trả lời cho câu hỏi của JohnS về "THAM GIA". Bất cứ ai có thể gửi một liên kết nơi nó có thể được giải thích? Tôi phải làm điều tương tự và nó sẽ rất hữu ích cho tôi.
Waseem

3
Không tham gia. Một truy vấn cho mỗi duy nhất activity_typeđể có được dữ liệu khác mà bạn cần.
vượt qua

21

Đây là triển khai của tôi về một luồng hoạt động, sử dụng mysql. Có ba lớp: Activity, ActivityFeed, Thuê bao.

Hoạt động thể hiện một mục hoạt động và bảng của nó trông như thế này:

id
subject_id
object_id
type
verb
data
time

Subject_idlà id của đối tượng thực hiện hành động, object_idid của đối tượng nhận hành động. typeverbmô tả chính hành động đó (ví dụ: nếu người dùng thêm nhận xét vào bài viết thì họ sẽ lần lượt là "bình luận" và "được tạo"), dữ liệu chứa dữ liệu bổ sung để tránh tham gia (ví dụ: nó có thể chứa tên chủ đề và họ, tiêu đề bài viết và url, nội dung bình luận, v.v.).

Mỗi Hoạt động thuộc về một hoặc nhiều Nguồn cấp dữ liệu Hoạt động và chúng có liên quan bởi một bảng trông như thế này:

feed_name
activity_id

Trong ứng dụng của mình, tôi có một nguồn cấp dữ liệu cho mỗi Người dùng và một nguồn cấp dữ liệu cho mỗi Mục (thường là các bài viết trên blog), nhưng chúng có thể là bất cứ thứ gì bạn muốn.

Người đăng ký thường là người dùng trang web của bạn, nhưng nó cũng có thể là bất kỳ đối tượng nào trong mô hình đối tượng của bạn (ví dụ: một bài viết có thể được đăng ký vào feed_action của người tạo).

Mỗi Người đăng ký thuộc về một hoặc nhiều Nguồn cấp dữ liệu Hoạt động và, như trên, chúng có liên quan bởi một bảng liên kết loại này:

feed_name
subscriber_id
reason

Các reasonlĩnh vực ở đây giải thích tại sao các thuê bao đã đăng ký thức ăn. Ví dụ: nếu người dùng đánh dấu một bài đăng trên blog, lý do là 'đánh dấu'. Điều này giúp tôi sau này trong việc lọc các hành động để thông báo cho người dùng.

Để lấy lại hoạt động cho một thuê bao, tôi thực hiện một phép nối đơn giản trong ba bảng. Việc tham gia diễn ra nhanh chóng vì tôi chọn một vài hoạt động nhờ một WHEREđiều kiện giống như bây giờ - time > some hours. Tôi tránh các phép nối khác nhờ vào trường dữ liệu trong bảng Activity.

Giải thích thêm về reasonlĩnh vực. Ví dụ: nếu tôi muốn lọc các hành động cho thông báo qua email cho người dùng và người dùng đã đánh dấu một bài đăng trên blog (và vì vậy anh ta đăng ký vào nguồn cấp dữ liệu bài đăng với lý do 'đánh dấu'), tôi không muốn người dùng nhận được email thông báo về các hành động trên mục đó, trong khi nếu anh ấy bình luận bài đăng (và vì vậy, nó đăng ký vào nguồn cấp dữ liệu với lý do 'bình luận') Tôi muốn anh ấy được thông báo khi người dùng khác thêm nhận xét vào cùng một bài đăng. Trường lý do giúp tôi phân biệt đối xử này (tôi đã triển khai nó thông qua lớp ActivityFilter), cùng với các tùy chọn thông báo của người dùng.


Nicolo martini tôi muốn thêm bình luận trả lời về hoạt động và hiển thị nó dưới nó, làm thế nào có thể với cấu trúc của bạn? Tôi nên thêm một bảng khác hoặc chỉ sử dụng cùng, nếu giống nhau, đề xuất của bạn là gì?
Basit

Hiệu suất của việc thực hiện này như thế nào? Bất kỳ thử nghiệm trên bàn lớn?
Joshua F. Rountree

16

Có một định dạng hiện tại cho luồng hoạt động đang được phát triển bởi một nhóm người hiểu biết.

http://activitystrea.ms/ .

Về cơ bản, mọi hoạt động đều có một diễn viên (người thực hiện hoạt động), một động từ (hành động của hoạt động), một đối tượng (trên đó diễn viên thực hiện) và một mục tiêu.

Ví dụ: Max đã đăng một liên kết đến tường của Adam.

Spec của JSON của họ đã đạt đến phiên bản 1.0 tại thời điểm viết, trong đó hiển thị mẫu cho hoạt động mà bạn có thể áp dụng.

Định dạng của chúng đã được BBC, Gnip, Google Buzz Gowalla, IBM, MySpace, Opera, Socialcast, Superfeedr, TypePad, Windows Live, YIID và nhiều người khác chấp nhận.


hi @sntran Tôi biết bài đăng này đã cách đây nhiều năm, nhưng tôi có một câu hỏi thêm về luồng hoạt động. Có cách nào bạn có thể giúp đỡ?
herwendy

Chắc chắn rồi. Câu hỏi của bạn là gì?
Sơn Trần-Nguyễn

Câu hỏi của tôi thực sự được đăng ở đây! liên kết . Tôi nghĩ rằng tôi có hiểu biết cơ bản về luồng hoạt động, nhưng tôi thực sự không chắc chắn cách triển khai nó (nghĩa là tôi phải sử dụng angular hay node.js?) Và từ đó, làm thế nào để tôi thực sự TẠO một luồng hoạt động với API JSON đến? Đây là những câu hỏi cơ bản như vậy, nhưng tôi không thể tìm thấy bất kỳ câu trả lời trực tuyến nào. Nếu bạn có thể giúp đỡ, tôi thực sự đánh giá cao nó. Cảm ơn bạn!
herwendy

13

Tôi nghĩ rằng một lời giải thích về cách hệ thống thông báo hoạt động trên các trang web lớn có thể được tìm thấy trong câu hỏi tràn ngăn xếp làm thế nào để các trang web mạng xã hội tính toán cập nhật bạn bè? , trong câu trả lời của Jeremy Wall . Ông đề nghị sử dụng Message Qeue và ông chỉ ra hai phần mềm nguồn mở thực hiện nó:

  1. ThỏMQ
  2. Apache QPid

Xem thêm câu hỏi Cách thức tốt nhất để thực hiện một luồng hoạt động xã hội là gì?


1

Bạn hoàn toàn cần một hàng đợi tin nhắn biểu diễn & phân phối. Nhưng nó không kết thúc ở đó, bạn sẽ phải đưa ra quyết định về việc lưu trữ dữ liệu liên tục và những gì tạm thời, v.v.

Dù sao, đó thực sự là một nhiệm vụ khó khăn, bạn của tôi nếu bạn đang theo đuổi một hệ thống hiệu suất cao và có thể mở rộng. Nhưng, tất nhiên một số kỹ sư hào phóng đã chia sẻ kinh nghiệm của họ về điều này. LinkedIn gần đây đã làm cho hệ thống xếp hàng tin nhắn của mình Kafka là nguồn mở. Trước đó, Facebook đã cung cấp Scribe cho cộng đồng nguồn mở. Kafka được viết bằng Scala và lúc đầu phải mất một thời gian để chạy nó nhưng tôi đã thử nghiệm với một vài máy chủ ảo. Nó thực sự rất nhanh.

http://blog.linkedin.com/2011/01/11/open-source-linkedin-kafka/

http://incubator.apache.org/kafka/index.html


0

Thay vì tự lăn, bạn có thể tìm đến dịch vụ của bên thứ ba được sử dụng thông qua API. Tôi đã bắt đầu một cái gọi là Collabinate ( http://www.collabinate.com ) có một phụ trợ cơ sở dữ liệu đồ thị và một số thuật toán khá tinh vi để xử lý một lượng lớn dữ liệu theo cách hiệu quả cao, đồng thời. Mặc dù nó không có nhiều chức năng như Facebook hay Twitter làm, nhưng điều đó không đủ cho hầu hết các trường hợp sử dụng mà bạn cần xây dựng các luồng hoạt động, nguồn cấp dữ liệu xã hội hoặc chức năng blog vào một ứng dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.