點贊功能,到底用 MySQL 仍是 Redis ?

真正聰明的人看似笨拙,實際上是不自炫耀;真正有才華的人看似木訥,實際上是不露鋒芒。mysql

點贊功能是目前app開發基本的功能 redis

今天咱們就來聊聊點贊、評論、收藏等這些場景的db數據庫設計問題~sql

1. 咱們先來看看場景的需求:

  • 顯示點贊數量
  • 判斷用戶是否點過贊,用於去重,必須的判斷
  • 顯示我的點贊列表,通常在用戶中心
  • 顯示文章點贊列表

咱們先看一下頭條和微博的例子
微信圖片_20200607092504.jpg
微信圖片_20200607092536.jpg
這兩個都是具備頂級流量的,後端確定有複雜的架構,咱們今天只談大衆化的方案。數據庫

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=?app

點贊數量能夠經過定時異步統計更新到post和user 表中。異步

數據量不大的時候,這種設計基本能夠知足需求了,nosql

缺點:

數據量大時,一張表在查詢時壓力巨大,須要分表,而不論用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作同步。
微信圖片_20200607092802.jpg
多數場景兩者是同時使用的,並不衝突。

下面說下redis做爲storage的方案:

場景a :顯示點贊數量

在點讚的地方,只是顯示一個點贊數量,能區分用戶是否點贊過,通常用戶不關心這個列表,這個場景只要一個數字就能夠了,當數量比較大時,通常顯示爲"7k" ,"10W" 這樣。

以文章id爲key

//以文章id=888爲例   
127.0.0.1:6379[2]> set star:tid:888 898 //設置點贊數量   
OK   
127.0.0.1:6379[2]> incr star:tid:888 //實現數量自增 (integer)   
899

場景b:點贊去重,避免重複點贊

要實現這個需求,必須有文章點讚的uid列表,以uid爲key場景c:通常在用戶中心,能夠看到用戶本身的點贊列表

這個需求可使用場景b的數據來實現。
微信圖片_20200607092905.jpg
場景d:文章的點贊列表,相似場景b,以文章id爲key

//以文章id=888爲例   
127.0.0.1:6379[2]> sadd star:list:tid:888 123 456 789 //點贊uid列表 (integer)   
3   
127.0.0.1:6379[2]> sismember star:list:tid:888 456 //判斷是否點贊 (integer)   
1

點讚的地方,若是點贊過顯示紅色,沒有則顯示黑白色,

今日頭條是沒有地方能夠看到點贊列表的,而微博點進去,詳情頁能夠看到點贊列表,可是隻會顯示最近的幾十條,沒有分頁顯示。

以下圖,我選了一條熱點,擁有衆多粉絲的「豬豬」
微信圖片_20200607093000.jpg
可能有人以爲,點贊列表沒人關心,存儲又會浪費大量資源,不如不存!可是,這個數據是必需要有的。兩點:

  • 去重。點贊數能夠不精確,但去重必須是精確的,
  • 另一個社交產品,用戶行爲的一點一滴都須要記錄,對於後續的用戶行爲分析和數據挖掘都是有意義的。

上面使用string存儲的用戶點贊數量,除了string,還能夠用hash來存儲,對文章id分塊,每100個存到一個hash,分別存入hash table,每一個文章id爲hash的一個key,value存儲點讚的用戶id,若是點贊用戶不少,避免id過多產生性能問題,能夠單列出來,用sorted set結構保存,熱點的畢竟是少數。
微信圖片_20200607093029.jpg
方案優缺點比對

hash:使用了更少的全局key ,節省了內存空間;可是也帶來了問題

如何根據文章id路由到對應的hash?

查找一個用戶id是在hash仍是set?存在不肯定性

使用hash雖然節省了空間,但增長了複雜度,如何選擇就看我的需求了。

除此以外,你還有其餘的方法嗎?

3. 數據一致性

redis做爲storage使用時,必定要作好數據的持久化,必須開啓 rdb 和 aof,這會致使業務只能使用一半的機器內存,因此要作好容量的監控,及時擴容。

另外只要有數據copy,就會有一致性問題,這就是另一個很重要的話題了。

相關文章
相關標籤/搜索