今天我們就來聊聊點贊、評論、收藏等這些場景的db數據庫設計問題~
1. 我們先來看看場景的需求:
顯示點贊數量
判斷用户是否點過贊,用於去重,必須的判斷
顯示個人點贊列表,一般在用户中心
顯示文章點贊列表
我們先看一下頭條和微博的例子
這兩個都是具有頂級流量的,後端肯定有複雜的架構,我們今天只談大眾化的方案。
2.1 mysql方案
mysql方案, 隨着nosql的流行,大數據的持續熱點,但是mysql仍然不可替代,對於大多數的中小項目,低於千萬級的數據量,採用mysql分表 cache,是完全可以勝任的,而且穩定性是其他方案無可比擬的:
-- 文章表
create table post {
post_id int(11) NOT NULL AUTO_INCREMENT,
......
star_num int(11) COMMENT '點贊數量'
}
-- 用户表
create table user {
user_id int(11) NOT NULL AUTO_INCREMENT,
......
star_num int(11) COMMENT '點贊數量'
}
-- 點贊表
create table star {
id int(11) NOT NULL AUTO_INCREMENT,
post_id,
user_id,
......
}
常用的查詢:
查詢用户點贊過的文章select post_id from star where user_id=?
查詢文章的點贊用户select user_id from star where post_id=?
點贊數量可以通過定時異步統計更新到post和user 表中。
數據量不大的時候,這種設計基本可以滿足需求了,
缺點:
數據量大時,一張表在查詢時壓力巨大,需要分表,而不論用post_id還是user_id來hash分表都與我們的需求有衝突,唯一的辦法就是做兩個表冗餘。這增加了存儲空間和維護工作量,還可能有一致性問題。
2.2 redis方案
當數據量達到上億的量,上cache是必經的階段,由於點贊這種動作很隨意,很多人看到大拇指就想點,所以數據量增長很快,數據規模上來後,對mysql讀寫都有很大的壓力,這時就要考慮memcache、redis進行存儲或cache。
為什麼一般都選擇redis, redis作為流行的nosql,有着豐富的數據類型,可以適應多個場景的需求。
採用redis有兩種用途,一種是storage,一種是純cache,需要 mysql一起。純cache就是把數據從mysql先寫入redis,用户先讀cache,miss後再拉取MySQL,同時cache做同步。
多數場景二者是同時使用的,並不衝突。
下面説下redis作為storage的方案:
場景a :顯示點贊數量
在點讚的地方,只是顯示一個點贊數量,能區分用户是否點贊過,一般用户不關心這個列表,這個場景只要一個數字就可以了,當數量比較大時,一般顯示為"7k" ,"10W" 這樣。
以文章id為key
要實現這個需求,必須有文章點讚的uid列表,以uid為key場景c:一般在用户中心,可以看到用户自己的點贊列表 這個需求可以使用場景b的數據來實現。 場景d:文章的點贊列表,類似場景b,以文章id為key 點讚的地方,如果點贊過顯示紅色,沒有則顯示黑白色, 今日頭條是沒有地方可以看到點贊列表的,而微博點進去,詳情頁可以看到點贊列表,但是隻會顯示最近的幾十條,沒有分頁顯示。 如下圖,我選了一條熱點,擁有眾多粉絲的“豬豬” 可能有人覺得,點贊列表沒人關心,存儲又會浪費大量資源,不如不存!但是,這個數據是必須要有的。兩點: 去重。點贊數可以不精確,但去重必須是精確的, 另外一個社交產品,用户行為的一點一滴都需要記錄,對於後續的用户行為分析和數據挖掘都是有意義的。 上面使用string存儲的用户點贊數量,除了string,還可以用hash來存儲,對文章id分塊,每100個存到一個hash,分別存入hash table,每個文章id為hash的一個key,value存儲點讚的用户id,如果點贊用户很多,避免id過多產生性能問題,可以單列出來,用sorted set結構保存,熱點的畢竟是少數。 方案優缺點比對 hash:使用了更少的全局key ,節省了內存空間;但是也帶來了問題 如何根據文章id路由到對應的hash? 查找一個用户id是在hash還是set?存在不確定性 使用hash雖然節省了空間,但增加了複雜度,如何選擇就看個人需求了。 除此之外,你還有其他的方法嗎? 3. 數據一致性 redis作為storage使用時,一定要做好數據的持久化,必須開啓 rdb 和 aof,這會導致業務只能使用一半的機器內存,所以要做好容量的監控,及時擴容。 另外只要有數據copy,就會有一致性問題,這就是另外一個很重要的話題了。以後有時間再細聊吧! 前幾天寫的一篇文章,受到眾多同行的熱情回覆,能和眾多同行一起交流,深感榮幸!對於工程類問題,沒有標準的方案,一千個人有一千個方案,哪個最適合你只有你自己知道!期待你更好的思路和方法。//以文章id=888為例
//以文章id=888為例