Thiết kế cơ sở dữ liệu Facebook?


133

Tôi đã luôn tự hỏi làm thế nào Facebook thiết kế mối quan hệ người dùng <->.

Tôi nghĩ bảng người dùng là như thế này:

user_email PK
user_id PK
password 

Tôi hình bảng với dữ liệu của người dùng (giới tính, tuổi, vv được kết nối qua email người dùng mà tôi sẽ giả sử).

Làm thế nào để nó kết nối tất cả bạn bè với người dùng này?

Một cái gì đó như thế này?

user_id
friend_id_1
friend_id_2
friend_id_3
friend_id_N 

Chắc là không. Bởi vì số lượng người dùng không xác định và sẽ mở rộng.


13
Có một trang Facebook Engineering có rất nhiều loại thông tin này, nhưng không hoàn toàn là những gì bạn đang hỏi. Bạn có thể muốn hỏi ở đó và xem nếu bạn có thể nhận được câu trả lời. facebook.com/FacebookEngineering
John Meagher

1
Google graph database. Nó chắc chắn không phải là một RDBMS.

Câu trả lời:


90

Giữ một bảng bạn giữ ID người dùng và sau đó là ID người dùng của bạn bè (chúng tôi sẽ gọi đó là FriendID). Cả hai cột sẽ là khóa ngoại trở lại bảng Người dùng.

Một số ví dụ hữu ích:

Table Name: User
Columns:
    UserID PK
    EmailAddress
    Password
    Gender
    DOB
    Location

TableName: Friends
Columns:
    UserID PK FK
    FriendID PK FK
    (This table features a composite primary key made up of the two foreign 
     keys, both pointing back to the user table. One ID will point to the
     logged in user, the other ID will point to the individual friend
     of that user)

Cách sử dụng ví dụ:

Table User
--------------
UserID EmailAddress Password Gender DOB      Location
------------------------------------------------------
1      bob@bob.com  bobbie   M      1/1/2009 New York City
2      jon@jon.com  jonathan M      2/2/2008 Los Angeles
3      joe@joe.com  joseph   M      1/2/2007 Pittsburgh

Table Friends
---------------
UserID FriendID
----------------
1      2
1      3
2      3

Điều này sẽ cho thấy Bob là bạn của cả Jon và Joe và Jon cũng là bạn với Joe. Trong ví dụ này, chúng tôi sẽ cho rằng tình bạn luôn có hai cách, vì vậy bạn sẽ không cần một hàng trong bảng như (2.1) hoặc (3.2) vì chúng đã được thể hiện theo hướng khác. Đối với các ví dụ trong đó tình bạn hoặc các mối quan hệ khác không rõ ràng theo hai chiều, bạn cũng cần có các hàng đó để biểu thị mối quan hệ hai chiều.


8
nghĩ về việc này không hiệu quả như thế nào - bạn phải thực hiện một truy vấn khác nhau trên các cột của nhiều-nhiều, gấp đôi thời gian tìm kiếm trung bình.
Anthony Giám mục

2
Cá nhân, tôi sẽ không muốn hai trường đó tạo một khóa chính tổng hợp. Một chìa khóa độc đáo, hoàn toàn. Chỉ số cụm trên khóa duy nhất đó, chắc chắn. Nhưng tôi cũng đặt một số loại nhận dạng không kết hợp là PK với chỉ mục không bao gồm. Điều đó sẽ cho phép các bảng khác cần FK "ID mối quan hệ bạn bè" dễ dàng liên kết với bảng này và các trình kích hoạt khác nhau có thể kích hoạt các sự kiện kết bạn, hủy kết bạn, v.v.
Jesse C. Choper

1
Họ nói rằng Facebook có khoảng 1'000'000 người dùng. Nếu người dùng trung bình có 100 bạn bè, điều đó có nghĩa là bảng sẽ chứa 100'000'000'000 hàng. Phân vùng MySQL?
veidelis

Hãy quên cách tiếp cận này. Nếu bạn nhận được một lượng người dùng nghiêm túc, nó chắc chắn sẽ trở nên rất chậm. Xem câu trả lời của tôi và thử tự đánh giá nó. Tôi đã thực hiện một số điểm chuẩn với 10k người dùng và 2,5 triệu kết nối hữu nghị và kết quả thật đáng thất vọng. Nếu bạn điều hành một cộng đồng nhỏ, nó sẽ hoạt động tốt nhưng có vấn đề về hiệu suất để xem xét.
burzum

7
bạn có thể chắc chắn rằng facebook không sử dụng RDBMS cho việc này, một kiến ​​thức phổ biến là họ, twitter và mọi người khác cần chạy các truy vấn như thế này sử dụng cơ sở dữ liệu đồ thị có hương vị. có ít nhất 69 người chưa bao giờ làm việc ở bất kỳ quy mô nào hoặc không biết làm toán ở quy mô nào.

51

Hãy xem sơ đồ cơ sở dữ liệu sau đây, được thiết kế ngược bởi Anatoly Lubarsky :

Lược đồ Facebook


7
Đây là sơ đồ lớp, không phải lược đồ cơ sở dữ liệu
Lemon Juice

2
Vì vậy, mỗi "Người dùng" có cơ sở dữ liệu chuyên dụng không? Giống như ở trên? Làm thế nào nó sẽ làm việc? Ví dụ: Khi người dùng đăng nhập vào FB kiểm tra xem đó có phải là User + Pass hợp lệ hay không và nếu facebook hợp lệ sẽ chuyển hướng họ đến cơ sở dữ liệu, sau đó hiển thị mọi thứ từ cơ sở dữ liệu trên
James111

Cửa hàng này chỉ có thông tin liên quan đến người dùng, tôi đặc biệt đang tìm kiếm Bài đăng và đối tượng của nó?
Waseem Ahmad Naeem

47

TL; DR:

Họ sử dụng một kiến ​​trúc ngăn xếp với các biểu đồ được lưu trong bộ nhớ cache cho mọi thứ phía trên đáy của ngăn xếp của họ.

Câu trả lời dài:

Tôi đã thực hiện một số nghiên cứu về điều này bởi vì tôi tò mò về cách họ xử lý lượng dữ liệu khổng lồ của họ và tìm kiếm nó một cách nhanh chóng. Tôi đã thấy mọi người phàn nàn về các tập lệnh mạng xã hội tùy chỉnh trở nên chậm chạp khi cơ sở người dùng phát triển. Sau khi tôi thực hiện một số điểm chuẩn cho bản thân chỉ với 10 nghìn người dùng và 2,5 triệu kết nối bạn bè - thậm chí không cố gắng bận tâm về quyền và nhóm thích và bài đăng trên tường - nó nhanh chóng nhận ra rằng phương pháp này là thiếu sót. Vì vậy, tôi đã dành thời gian tìm kiếm trên web về cách làm nó tốt hơn và tìm thấy bài viết chính thức này của Facebook:

Tôi thực sự khuyên bạn nên xem phần trình bày của liên kết đầu tiên ở trên trước khi tiếp tục đọc. Đây có lẽ là lời giải thích tốt nhất về cách FB hoạt động đằng sau hậu trường bạn có thể tìm thấy.

Video và bài viết cho bạn biết một số điều:

  • Họ đang sử dụng MySQL ở cuối ngăn xếp của họ
  • Phía trên SQL DB có lớp TAO chứa ít nhất hai cấp bộ đệm và đang sử dụng biểu đồ để mô tả các kết nối.
  • Tôi không thể tìm thấy bất cứ điều gì trên phần mềm / DB mà họ thực sự sử dụng cho các biểu đồ được lưu trong bộ nhớ cache của họ

Chúng ta hãy xem điều này, các kết nối bạn bè ở trên cùng bên trái:

nhập mô tả hình ảnh ở đây

Vâng, đây là một biểu đồ. :) Nó không cho bạn biết cách xây dựng nó trong SQL, có một số cách để làm điều đó nhưng trang web này có một số cách tiếp cận khác nhau. Chú ý: Hãy xem xét rằng một DB quan hệ chính là nó: Nó được cho là lưu trữ dữ liệu chuẩn hóa, không phải là một cấu trúc biểu đồ. Vì vậy, nó sẽ không hoạt động tốt như một cơ sở dữ liệu đồ thị chuyên dụng.

Cũng xem xét rằng bạn phải thực hiện các truy vấn phức tạp hơn chỉ là bạn bè của bạn bè, ví dụ như khi bạn muốn lọc tất cả các vị trí xung quanh tọa độ đã cho mà bạn và bạn bè của bạn thích. Một đồ thị là giải pháp hoàn hảo ở đây.

Tôi không thể cho bạn biết cách xây dựng nó để nó hoạt động tốt nhưng rõ ràng nó đòi hỏi một số thử nghiệm và lỗi và điểm chuẩn.

Đây là tôi thất vọng thử nghiệm cho chỉ phát hiện bạn của bạn bè:

Lược đồ DB:

CREATE TABLE IF NOT EXISTS `friends` (
`id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `friend_id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

Truy vấn bạn bè:

(
        select friend_id
        from friends
        where user_id = 1
    ) union (
        select distinct ff.friend_id
        from
            friends f
            join friends ff on ff.user_id = f.friend_id
        where f.user_id = 1
    )

Tôi thực sự khuyên bạn nên tạo cho bạn một số dữ liệu mẫu có ít nhất 10 nghìn hồ sơ người dùng và mỗi người trong số họ có ít nhất 250 kết nối bạn bè và sau đó chạy truy vấn này. Trên máy của tôi (i7 4770k, SSD, RAM 16gb) kết quả là ~ 0,18 giây cho truy vấn đó. Có lẽ nó có thể được tối ưu hóa, tôi không phải là thiên tài DB (đề xuất được chào đón). Tuy nhiên, nếu tỷ lệ này tuyến tính, bạn đã ở mức 1,8 giây cho chỉ 100 nghìn người dùng, 18 giây cho 1 triệu người dùng.

Điều này có thể vẫn nghe có vẻ ổn đối với ~ 100 nghìn người dùng nhưng hãy cân nhắc rằng bạn chỉ tìm nạp bạn bè của bạn bè và không thực hiện bất kỳ truy vấn phức tạp nào như "chỉ hiển thị cho tôi các bài đăng từ bạn bè của bạn + kiểm tra quyền nếu tôi được phép hoặc KHÔNG được phép để xem một số trong số họ + thực hiện một truy vấn phụ để kiểm tra xem tôi có thích ai trong số họ không ". Bạn muốn để DB thực hiện kiểm tra xem bạn có thích một bài đăng hay không hoặc bạn sẽ phải làm bằng mã. Cũng xem xét rằng đây không phải là truy vấn duy nhất bạn chạy và bạn có nhiều hơn người dùng hoạt động cùng một lúc trên một trang web phổ biến hơn hoặc ít hơn.

Tôi nghĩ rằng câu trả lời của tôi trả lời câu hỏi làm thế nào Facebook thiết kế mối quan hệ bạn bè của họ rất tốt nhưng tôi xin lỗi vì tôi không thể cho bạn biết cách triển khai nó theo cách nó sẽ hoạt động nhanh. Việc triển khai một mạng xã hội là dễ dàng nhưng đảm bảo rằng nó hoạt động tốt rõ ràng là không - IMHO.

Tôi đã bắt đầu thử nghiệm với OrientDB để thực hiện các truy vấn biểu đồ và ánh xạ các cạnh của tôi tới SQL DB bên dưới. Nếu tôi hoàn thành nó tôi sẽ viết một bài báo về nó.


vì vậy .. bạn đã bao giờ nhận được xung quanh để viết bài?
FlowUI. SimpleUITesting.com

1
Không, tôi khá bận rộn bên cạnh việc lập trình và không có thời gian và tâm trạng để làm việc đó. Câu trả lời ở đây chứa mọi thứ bạn cần biết nếu bạn muốn triển khai các hiệp hội bạn bè biểu diễn. Hoặc lưu trữ danh sách bạn bè trên mỗi người dùng hoặc ánh xạ DB quan hệ của bạn theo từng phần hoặc toàn bộ vào biểu đồ và truy vấn DB biểu đồ. Bạn có thể sử dụng OrientDB hoặc Neo4j cho điều đó. Tôi rất thích viết phần mềm mạng xã hội nguồn mở của riêng mình nhưng cũng có rất nhiều thứ khác để làm. Bất cứ điều gì bạn làm: Làm điểm chuẩn. :)
burzum

Vẫn không có. Nhưng tài liệu của OrientDB giải thích các kết nối bạn bè và mọi thứ khác có thể được mô hình hóa khi hiểu được những điều cơ bản. directiondb.com/docs/2.1/Tutorial-Working-with-graphs.html Nếu bạn muốn sử dụng DB quan hệ làm nền tảng thì bạn chỉ cần thêm một số mã trong các cuộc gọi lại "sau khi lưu" và "sau khi xóa" để cập nhật đồ thị DB (mà bạn sẽ sử dụng để đọc dữ liệu). Nếu bạn không có các cuộc gọi lại như vậy triển khai chúng nhưng tôi đoán hầu như tất cả các loại triển khai và khung ORM đều có thứ gì đó tương tự. Trên thực tế, OrientDB cũng có thể lưu trữ tài liệu.
burzum

1
vì vậy .. bạn đã bao giờ nhận được xung quanh để viết bài?
Connor Gurney

1
Vẫn không có nhưng chúng tôi làm một cái gì đó tương tự tại nơi làm việc: Chúng tôi ánh xạ dữ liệu quan hệ của mình sang chỉ mục Tìm kiếm đàn hồi, như tôi đã viết trong nhận xét của mình trước đây, đó chỉ là vấn đề nhận dữ liệu bạn muốn lưu trữ trong chỉ mục hoặc biểu đồ sau một hành động nhất định gọi lại (afterSave () / afterDelete () trong trường hợp của chúng tôi) và sau đó cập nhật chỉ mục hoặc biểu đồ. Khá đơn giản? :) Nhân tiện, có thể được thực hiện tương tự với danh sách bạn bè, điều đó thực sự không quan trọng nếu bạn lưu trữ chúng trong ES, biểu đồ hoặc bộ nhớ cache dựa trên bộ nhớ (miễn là bạn có đủ RAM). Điều đó thực sự không khó, phần khó là làm cho toàn bộ quy mô khi bạn phát triển.
burzum

32

Đặt cược tốt nhất của tôi là họ đã tạo ra một cấu trúc đồ thị . Các nút là người dùng và "tình bạn" là các cạnh.

Giữ một bảng người dùng, giữ một bảng cạnh khác. Sau đó, bạn có thể giữ dữ liệu về các cạnh, như "ngày họ trở thành bạn bè" và "trạng thái được phê duyệt", v.v.


40
Tôi có cảm giác bạn sẽ phải giải thích thêm một chút cho một số người ở đây.
TheTXI

4
Tôi nghĩ một câu hỏi thú vị hơn là làm thế nào để duy trì cấu trúc khổng lồ như vậy (chúng ta đang nói về 200 triệu nút và hàng tỷ cạnh) theo cách mà nó có thể dễ dàng được tìm kiếm và cập nhật.
Dirk Vollmar

1
@divo: sử dụng thông minh các chỉ mục và phân vùng.
belgariontheking

20

Đó rất có thể là mối quan hệ nhiều đến nhiều:

Danh sách bạn bè (bảng)

user_id -> users.user_id
friend_id -> users.user_id
friendVisibilityLevel

BIÊN TẬP

Bảng người dùng có thể không có user_email dưới dạng PK, có thể là một khóa duy nhất.

người dùng (bảng)

user_id PK
user_email
password

4
Mặc dù điều này chắc chắn có ý nghĩa nhất, tôi sẽ nghĩ rằng hiệu suất sẽ rất khủng khiếp khi có bao nhiêu người dùng Facebook và bao nhiêu bạn bè mỗi người dùng Facebook có.
Kevin Pang

17

Hãy xem những bài viết này mô tả cách LinkedIn và Digg được xây dựng:

Ngoài ra còn có "Dữ liệu lớn: Quan điểm từ Nhóm dữ liệu Facebook" có thể hữu ích:

http://developer.yahoo.net/bloss/theater/archives/2008/01/nextyahoonet_big_data_viewpoint_from_the_fac.html

Ngoài ra, có bài viết này nói về cơ sở dữ liệu không liên quan và cách chúng được sử dụng bởi một số công ty:

http://www.readwriteweb.com/archives/is_the_relational_database_doomed.php

Bạn sẽ thấy rằng các công ty này đang xử lý kho dữ liệu, cơ sở dữ liệu được phân vùng, bộ đệm dữ liệu và các khái niệm cấp cao hơn so với hầu hết chúng ta không bao giờ xử lý hàng ngày. Hoặc ít nhất, có lẽ chúng ta không biết rằng chúng ta làm.

Có rất nhiều liên kết trên hai bài viết đầu tiên sẽ cung cấp cho bạn một cái nhìn sâu sắc hơn.

CẬP NHẬT 20/10/2014

Murat Demirbas đã viết một bản tóm tắt về

  • TAO: Kho lưu trữ dữ liệu phân tán của Facebook cho biểu đồ xã hội (ATC'13)
  • F4: Hệ thống lưu trữ BLOB ấm áp của Facebook (OSDI'14)

http://muratbuffalo.blogspot.com/2014/10/facebooks-software-arch architecture.html

HTH


9

Không thể truy xuất dữ liệu từ RDBMS cho dữ liệu bạn bè của người dùng cho dữ liệu vượt quá nửa tỷ đồng một lúc vì vậy Facebook đã triển khai việc này bằng cơ sở dữ liệu băm (không có SQL) và họ đã mở cơ sở dữ liệu có tên Cassandra.

Vì vậy, mỗi người dùng có khóa riêng và các chi tiết bạn bè trong hàng đợi; để biết làm thế nào cassandra làm việc này nhìn vào điều này:

http://prasath.posterous.com/cassandra-55


Rất thú vị, cảm ơn bạn của tôi. Khi nào họ chuyển sang cassandra từ sql? bạn có biết không
Marin

1
Lưu ý: Không gian Posterous đã chết ... vì vậy liên kết.
TechNyquist

6

Bài đăng gần đây vào tháng 6 năm 2013 này đi sâu vào một số chi tiết để giải thích sự chuyển đổi từ cơ sở dữ liệu quan hệ sang các đối tượng có liên kết cho một số loại dữ liệu.

https://www.facebook.com/notes/facebook-engineering/tao-the-power-of-the-graph/10151525983993920

Có một bài báo dài hơn có sẵn tại https://www.usenix.org/conference/atc13/tao-facebook's-distribution-data-store-social-graph


5

Bạn đang tìm chìa khóa nước ngoài. Về cơ bản, bạn không thể có một mảng trong cơ sở dữ liệu trừ khi nó có bảng riêng.


Lược đồ ví dụ:

    Bảng người dùng
        người dùng PK
        dữ liệu khác
    Bảng bạn bè
        userID - FK tới bảng của người dùng đại diện cho người dùng có bạn bè.
        friendID - Bảng FK to Users 'đại diện cho id người dùng của bạn bè

5
Tại sao các downvote? Ít nhất hãy cho ai đó biết lý do tại sao bạn đánh giá thấp họ.
Sasha Chedygov

3
@freak: Tại sao? Toàn bộ khái niệm bỏ phiếu trên trang web này là để bỏ phiếu là ẩn danh. Tại sao bạn cảm thấy sai lầm được hưởng bất cứ điều gì?
GEOCHET

4
Đặc biệt khi đó là một câu trả lời hợp lệ và được lặp lại bởi các câu trả lời khác (mặc dù tôi đã không sao chép từ chúng, khi tôi trả lời, không có câu trả lời nào)
Malfist

4
@TheTXI: Tôi nghĩ rằng các bình luận về downvote là một phép lịch sự, đặc biệt là các câu trả lời rõ ràng không xứng đáng với chúng, nhưng tôi cũng đồng ý rằng các bình luận không nên bắt buộc.
Robert S.

2
Những người downvote ẩn danh trên các câu trả lời không rõ ràng là những người sợ rằng lý luận nông cạn của họ sẽ bị phơi bày nếu họ để lại một bình luận giải thích một downvote.
Vinayak


1

Hãy nhớ rằng các bảng cơ sở dữ liệu được thiết kế để phát triển theo chiều dọc (nhiều hàng hơn), không theo chiều ngang (nhiều cột hơn)


24
KHÔNG BAO GIỜ QUÊN! Cha tôi đã chết vì một bảng db đã phát triển quá xa theo chiều dọc cho các cột của nó. Con sẽ nhớ bố.
belgariontheking

1
hmm, tại sao các downvote? Và bình luận ở trên này không có ý nghĩa.
Neil N

2
Không, bình luận không có ý nghĩa. Có vẻ như ai đó đã cố gắng để vui vẻ, vì vậy đừng bận tâm.
Dirk Vollmar

0

Về hiệu suất của một bảng nhiều-nhiều, nếu bạn có 2 int 32 bit liên kết ID người dùng, thì bộ lưu trữ dữ liệu cơ bản của bạn cho 200.000.000 người dùng trung bình 200 người bạn mỗi người chỉ dưới 300 GB.

Rõ ràng, bạn sẽ cần một số phân vùng và lập chỉ mục và bạn sẽ không giữ nó trong bộ nhớ cho tất cả người dùng.


0

Có lẽ có một bảng lưu trữ mối quan hệ người dùng <->, nói "frnd_list", có các trường 'user_id', 'frnd_id'.

Bất cứ khi nào người dùng thêm người dùng khác làm bạn bè, hai hàng mới sẽ được tạo.

Ví dụ: giả sử id của tôi là 'deep9c' và tôi thêm người dùng có id 'akash3b' làm bạn của tôi, sau đó hai hàng mới được tạo trong bảng "frnd_list" với các giá trị ('deep9c', 'akash3b') và ('akash3b ',' Deep9c ').

Bây giờ khi hiển thị danh sách bạn bè cho một người dùng cụ thể, một sql đơn giản sẽ thực hiện điều đó: "select frnd_id từ frnd_list trong đó user_id =" trong đó id của người dùng đã đăng nhập (được lưu dưới dạng thuộc tính phiên).

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.