1. 程式人生 > >推薦:新浪微博,騰訊微博 mysql資料庫主表設計

推薦:新浪微博,騰訊微博 mysql資料庫主表設計

使用者資訊表(t_user_info)

欄位名稱

位元組數

型別

描述

User_id

4

uint32

使用者編號(主鍵)

User_name

20

Char[20]

名稱

Msg_count

4

uint32

釋出訊息數量,可以作為t_msg_info水平切分新表的auto_increment

Fans_count

4

uint32

粉絲數量

Follow_count

4

Uint32

關注物件數量

備註:以User_id取模分表

 使用者之間關係表(t_user_relation),必須有關注與被關注的關係

欄位名稱

位元組數

型別

描述

User_id

4

uint32

使用者編號(聯合主鍵)

Follow_id

4

uint32

被關注者編號(聯合主鍵)

Type

1

Uint8

關係型別(0,粉絲;1,關注)

備註:關係是單向的,以User_id取模分表

使用者訊息索引表(t_uer_msg_index)

欄位名稱

位元組數

型別

描述

User_id

4

uint32

使用者編號(聯合主鍵)

Author_id

4

uint32

訊息釋出者編號(可能是被關注者,也可能是自己)(聯合主鍵)

Msg_id

4

uint32

訊息編號(由訊息釋出者的msg_count自增)(聯合主鍵)

Time_t

4

Uint32

釋出時間(必須是訊息元資料產生時間)

備註:此表就是當我們點選“我的首頁”時拉取的訊息列表,只是索引,Time_t對這些訊息進行排序

訊息與訊息關係表(t_msg_msg_relation)

欄位名稱

位元組數

型別

描述

Reference_id

4

uint32

引用訊息使用者編號(聯合主鍵)

Reference _msg_id

4

uint32

引用訊息編號(聯合主鍵)

Referenced_id

4

uint32

訊息釋出者編號

Referenced _msg_id

4

uint32

被引用訊息編號

Type

1

Uint8

操作型別(1,評論;2,轉發)

Time_t

4

Uint32

釋出時間

Page_index

4

Uint32

轉發或者評論頁碼

備註:以Reference_id取模分表。

騰訊微博比新浪微博好的一點是一個訊息的所有評論和轉發都是被固定頁碼,這樣在點選看評論的時候搜尋效率更高,因為多了一個where Page_index的定位條件,當然帶來的問題就是可能看到有些頁的評論排版並不是滿頁,這就是因為標識為這個Page_index的評論有刪除操作。

訊息元資料表(t_msg_info)

欄位名稱

位元組數

型別

描述

User_id

4

uint32

發訊息使用者編號(聯合主鍵)

Msg_id

4

uint32

訊息編號(聯合主鍵)

Content

140

Char[140]

訊息內容

Type

1

Uint8

訊息型別(0,原創;1,評論;2,轉發)

Commented_count

4

Uint32

評論過數量(只增不減,刪除評論不影響此值,可以作為評論多頁顯示的頁碼)

Comment_count

4

Uint32

保留的評論數量

Transferred_count

4

Uint32

轉發過數量(只增不減,刪除轉發不影響此值,可以作為轉發多頁顯示的頁碼)

Transfer_count

4

Uint32

保留的轉發數量

Time_t

4

Uint32

釋出時間

 備註:訊息元資料中,content像可能存在圖片,這部分可以在分散式檔案系統中儲存。在2011年資料庫大會上聽楊海潮的演講,對於nosql 也有涉及,本人能力有限,對這部分的職責還不清楚,希望高人指點。

非常推崇楊海潮ppt中的歸檔做法,因為微博是有時間軸線的,對於一定時間之前的記錄可以分層次歸檔,這樣在前端的最新的資料表的壓力就會減輕很多。

業務邏輯:

1.A關注B

1)在t_user_relation_A中新增

A

B

1

2)在t_user_relation_B中新增

B

A

0

2.原創發訊息

1)在t_msg_info_A中新增這條元訊息,type為0

2)更新t_user_info_A中Msg_count

3)在t_uer_msg_index_A中插入A發的這條訊息的索引(A的編號和訊息編號)

4)在t_user_relation_A中找到所有關注A的人,比如B,C,D,E,F等等。併發在這些使用者的t_uer_msg_index中插入A的這條資訊索引,

    比如名人微博可以併發多個程序來實現對粉絲的訊息同步。

3.A轉發B的訊息msg_b

1)在t_msg_info_A中新增這條元訊息msg_a,type為2

2)更新t_user_info_A中Msg_count

3)在t_uer_msg_index_A中插入A發的這條訊息的索引(A的編號和訊息編號)

4)在t_msg_info_B中更新msg_b的Transferred_count和Transfer_count

5)在t_msg_msg_relation中新增User_a,msg_a與User_b,msg_b的轉發關係,page_index為Transferred_count%page_count

4.A評論B的訊息msg_b

1)在t_msg_info_A中新增這條元訊息msg_a,type為1

2)更新t_user_info_A中Msg_count

3)在t_uer_msg_index_A中插入A發的這條訊息的索引(A的編號和訊息編號)

4)在t_msg_info_B中更新msg_b的Commented_count和Comment_count

5)在t_msg_msg_relation中新增User_a,msg_a與User_b,msg_b的評論關係,page_index為Commented_count%page_count

5.A刪除訊息msg_a

1)刪除t_msg_info中的元資料msg_a

2)刪除t_uer_msg_index_A中的User_a,msg_a行記錄

3)備註:如果A的msg_a被別人評論或者引用,那麼在對方檢視評論或者轉發的時候會提示“原訊息已被作者刪除”

6.A刪除轉發訊息msg_a

1)刪除t_msg_info_A中的元資料msg_a

2)刪除t_uer_msg_index_A中的User_a,msg_a行記錄

3)在t_msg_msg_relation_A表中找到msg_a的源訊息,即B的msg_b

4)刪除t_msg_msg_relation_A中user_a,msg_a和user_b,msg_b的轉發關係

5)更新t_msg_info_B中msg_b記錄的Transfer_count,減1

7.A刪除評論訊息msg_a

1)刪除t_msg_info_A中的元資料msg_a

2)刪除t_uer_msg_index_A中的User_a,msg_a行記錄

3)在t_msg_msg_relation_A表中找到msg_a的源訊息,即B的msg_b

4)刪除t_msg_msg_relation_A中user_a,msg_a和user_b,msg_b的評論關係

5)更新t_msg_info_B中msg_b記錄的Commecnt_count,減1

8.A拉取全部訊息

1)從t_uer_msg_index_A中拉取Author_id,Msg_id,Time_t索引,並以Time_t排序

2)通過頁碼和每頁count控制返回結果數量,這樣避免了server io 壓力衝擊

5月25日更新:

1)條件允許的話,所有的index表可以放到記憶體中,全部cache,而元資料直接ssd,這樣讀速度會提高很多,當然也要做好熱備

2)t_user_relation表最好做合併儲存

5月27日更新:

1)在第二步原創發訊息要通知給粉絲,這時如果是明星,那麼推送的數量可能數百萬,新浪採取的做法是對這數百萬粉絲進行區別對待,按照活躍度劃分為幾個層級,每個層級有一個推送時效限定,這樣可以做到最想看到這個資訊的人能夠最及時的看到明星動態

2)用硬體來提升速度,將所有index表放在memory上,元資料放在ssd上,資料可以現在這兩層上做處理,並定時持久化到mysql中

3)提供批量處理介面,比如拉取最新更新索引

4)在一定限度上容忍不一樣,但要實現最終一致性

6月1日更新:

6月30日更新:

在新浪微博中,評論和轉發都與原創訊息是一樣的獨立記錄,只不過多了一條訊息關係記錄,在展現的時候除了要展現自己新增的轉發內容或評論內容之外,還需要將最原始的那條目標訊息取出來。

12月8日更新:

訊息與訊息關係表(t_msg_msg_relation)的備註中,應該是以Referenced_id取模分裂

2014年11月11日更新:

使用者A轉發使用者B的訊息meg_b,其實也是會產生一個訊息元資料msg_a,而msg_a與msg_b是轉發關係而已,從另一層面上說,也可以理解為A做了一次原創,這次產生的訊息也會push到A的關注著訊息列表中。

現在新浪微博可以看到哪些人轉發了訊息msgA, 轉發內容是怎樣的。這需要做一種反向對映,就是一個msgA對應一個msgXXX列表。簡單點,可以直接一個kv儲存,v是一個佇列,mysql與nosql都可以很方便的搞定


16年10月20日更新: