百萬級用戶量的站內信群發數據庫設計


轉載自:http://www.itivy.com/ivy/archive/2011/6/3/sms-db-design-of-million-user.html


隨着WEB2.0的發展,用戶之間的信息交互也變得十分龐大,而且實時性要求越來越高。現在很多SNS網站和一部分CMS網站都廣泛地應用了站內信這一模塊,這個看似簡單的東西其實背后隱藏着很多需要設計師重視的設計細節,要做好這個“郵遞員”是很不容易的。為什么這么說呢?下面我們就一步步來探索設計一個百萬級用戶量的站內信群發數據庫,看完以后你就會明白什么是真正可靠高效的“郵遞員”。

1、幾十——幾百的用戶量

這樣的網站規模最小,可能是一個中小企業的CMS系統,面對這樣的用戶量,我們就不必要考慮短消息數據量太大的問題了,所以按照怎么方便怎么來的原則,群發就每人復制一條消息數據,這樣用戶可以自己管理自己的消息,可以非常方便進行“已讀、未讀、刪除”等操作。按照這個思路,我們的數據庫設計如下:

表T_Message

1
2
3
4
5
6
Id            bigint      --消息ID
SenderId      bigint      --發送者ID
ReceiverId    bigint      --接收者ID
SendTime      datetime    --發送時間
ReadFlag      tinyint     --已讀標志
MessageText   text        --消息正文
這樣,我們接受自己的消息時只要做如下查詢:
1
SELECT * FROM T_Message WHERE ReceiverId=myid
查詢自己的未讀消息只要做如下查詢:
1
SELECT * FROM T_Message WHERE ReceiverId=myid and ReadFlag=0
這種方法很簡單,可能是我們第一個想到的,對於這樣的用戶量的情況這樣的設計確實也足夠了。

 

2、幾千——幾萬的用戶量

用戶量到了這樣的級哦別,這個網站應該算是比較大了,筆者估計,可能是一個地區性的SNS網站。那么面對這樣的用戶量,我們又該如何來設計站內信群發呢?上面第一種思路還行得通嗎?應該這樣說,如果勉強要用上面那種設計,也是可以的,只不過T_Message可能要考慮分區。但是,大家會不會覺得消息正文復制那么多條對於這樣的用戶量來講空間浪費太大,因為考慮到接收者一般是不修改消息正文的,所以我們可以讓所有接收者共享一條消息正文。具體數據庫設計方法和上面大同小異:

T_Message

1
2
3
4
5
6
Id              bigint      --消息ID
SenderId        bigint      --發送者ID
ReceiverId      bigint      --接收者ID
SendTime        datetime    --發送時間
ReadFlag        tinyint     --已讀標志
MessageTextId   bigint      --這里把消息正文內容換成消息正文Id
T_MessageText

1
2
3
Id              bigint      --ID標識
SenderId        bigint      --發送者ID
MessageText     text        --消息正文

這樣,我們就大大節省了消息的存儲空間,但是查詢的時候就稍微麻煩一點,就需要進行聯合查詢了,查詢自己的未讀消息可以這樣(意思一下,可能還有更高效的查詢方式):

1
2
3
SELECT T_Message.*,T_MessageText.* FROM T_Message
INNER JOIN T_MessageText ON T_Message.MessageTextId=T_MessageText.Id
WHERE T_Message.ReceiverId=myid AND T_Message.ReadFlag=0
用這種方法除了正文我們不能隨便刪除外,用戶還是可以自己管理自己的消息。

 

3、百萬級大用戶量

如果一個網站到了百萬級的用戶量了,那我不得不膜拜該網站和網站經營者了,因為經營這樣的網站一直是筆者的夢想:)好了,回歸正題,如果這樣的系統放你面前,讓你設計一個站內信群發數據庫,你該何去何從,總之,上面兩種常規的辦法肯定是行不通了的,因為龐大的數據量會讓消息表撐爆,即使你分區也無濟於事。這時候作為一個系統架構師的你,可能不僅僅要從技術的角度去考慮這個問題,更要從用戶實際情況去着手尋找解決問題的辦法。這里,有一個概念叫“活躍用戶”,即經常登錄網站的用戶,相對於那些一時沖動注冊而接下來又從來不登錄的用戶來說,活躍用戶對網站的忠誠度很高,從商業的角度來講,忠誠的客戶享受更高端的服務。

根據這個思路,我們來探索一種方法。假設網站有500萬注冊用戶,其中活躍用戶為60萬(這個比例真很不錯了),現在我們要對所有用戶群發一封致謝信。還是上面兩張表,首先我們可以先往消息表中插入一條群發標識為-1的消息,這里我們用字段SourceMessageId(原始消息)來標識(-1為原始群發消息本身,其他則是原始消息id),這樣其實群發的工作已經完成了,用戶可以看到這條公共的消息了。但是用戶需要有消息的控制權,所以必須讓每個用戶擁有一條自己的消息。要達到這個目的,我們可以讓用戶登錄時檢查是否已經拷貝原始消息,如果沒有拷貝,則拷貝一份原始消息並插入消息表,群發標識為原始消息的id;如果已經存在原始消息的拷貝,則什么都不做。這樣,我們就只要為這60萬活躍用戶消耗消息空間就可以了。具體數據庫設計如下:

T_Message

1
2
3
4
5
6
7
Id                  bigint      --消息ID
SenderId            bigint      --發送者ID
ReceiverId          bigint      --接收者ID,如果為原始群發消息則為-1
SendTime            datetime    --發送時間
ReadFlag            tinyint     --已讀標志,如果為原始群發消息則統一為0未讀
SourceMessageId     bigint      --如果為-1則為原始群發消息,其他則為原始消息id
MessageTextId       bigint      --這里把消息正文內容換成消息正文Id
T_MessageText 與上面方法的一樣。

當然,如果你的活躍用戶達到100%,那這種方法相對前一種就沒有優勢了,但這種情況基本上不太可能,所以,筆者覺得這種方法來處理大用戶量的消息群發還是可行的。

 

4、總結

本文只是大致闡述了實現的原理,很多細節都忽略沒有考慮,純粹一個設計想法而已,有興趣的朋友可以去自己實踐一下,另外,筆者對數據庫也不是很精通,如果有哪里闡述錯誤的還請指出,讓我們一起進步。

 

5、如果你喜歡設計和架構,你可能還會喜歡以下文章

Facebook和人人網的網站后台架構對比

facebook圖片存儲架構技術全解析

各大網站架構總結筆記

一步步構建大型網站架構

大型網站架構不得不考慮的10個問題

 

本文為筆者原創,歡迎轉載,但請在頁面明顯處表明原文鏈接,謝謝!
原文鏈接:http://www.itivy.com/ivy/archive/2011/6/3/sms-db-design-of-million-user.html



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM