<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          實戰(zhàn)篇:點贊功能,用 MySQL 還是 Redis 好 ?

          共 2679字,需瀏覽 6分鐘

           ·

          2020-07-28 12:16



          點擊上方藍色“程序猿DD”,選擇“設(shè)為星標”

          回復(fù)“資源”獲取獨家整理的學(xué)習(xí)資料!

          88754fd0aa9a4da2234cf21ed25a9ae8.webp

          作者 |?一起web編程

          來源 |?toutiao.com/i6825148720728769028

          點贊功能是目前app開發(fā)基本的功能

          今天我們就來聊聊 點贊、評論、收藏等這些場景的db數(shù)據(jù)庫設(shè)計問題,

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


          • 顯示點贊數(shù)量

          • 判斷用戶是否點過贊,用于去重,必須的判斷

          • 顯示個人點贊列表,一般在用戶中心

          • 顯示文章點贊列表

          我們先看一下頭條和微博的例子

          552af9bdfd3943cc52724c62a6644bb5.webp

          9d5e6d9540605a42e2cf4078b93b9140.webp

          這兩個都是具有頂級流量的,后端肯定有復(fù)雜的架構(gòu),我們今天只談大眾化的方案。

          2.1 mysql方案

          mysql方案, 隨著nosql的流行,大數(shù)據(jù)的持續(xù)熱點,但是mysql仍然不可替代,對于大多數(shù)的中小項目,低于千萬級的數(shù)據(jù)量,采用mysql分表+cache,是完全可以勝任的,而且穩(wěn)定性是其他方案無可比擬的:

          --?文章表

          create?table?post?{

          ????????post_id?int(11)?NOT?NULL?AUTO_INCREMENT,

          ????????......

          ????????star_num?int(11)?COMMENT?'點贊數(shù)量'

          }

          --?用戶表

          create?table?user?{

          ????????user_id?int(11)?NOT?NULL?AUTO_INCREMENT,

          ????????......

          ????????star_num?int(11)?COMMENT?'點贊數(shù)量'

          }

          --?點贊表

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

          點贊數(shù)量可以通過定時異步統(tǒng)計更新到post和user 表中。

          數(shù)據(jù)量不大的時候,這種設(shè)計基本可以滿足需求了,

          缺點:

          數(shù)據(jù)量大時,一張表在查詢時壓力巨大,需要分表,而不論用post_id還是user_id來hash分表都與我們的需求有沖突,唯一的辦法就是做兩個表冗余。這增加了存儲空間和維護工作量,還可能有一致性問題。

          2.2 redis方案

          當(dāng)數(shù)據(jù)量達到上億的量,上cache是必經(jīng)的階段,由于點贊這種動作很隨意,很多人看到大拇指就想點,所以數(shù)據(jù)量增長很快,數(shù)據(jù)規(guī)模上來后,對mysql讀寫都有很大的壓力,這時就要考慮memcache、redis進行存儲或cache。

          為什么一般都選擇redis, redis作為流行的nosql,有著豐富的數(shù)據(jù)類型,可以適應(yīng)多個場景的需求。

          采用redis有兩種用途,一種是storage,一種是純cache,需要+mysql一起。純cache就是把數(shù)據(jù)從mysql先寫入redis,用戶先讀cache,miss后再拉取MySQL,同時cache做同步。

          f74c1d1187df514cd2314400d73dd2a2.webp

          多數(shù)場景二者是同時使用的,并不沖突。

          下面說下redis作為storage的方案:

          場景a :顯示點贊數(shù)量

          在點贊的地方,只是顯示一個點贊數(shù)量,能區(qū)分用戶是否點贊過,一般用戶不關(guān)心這個列表,這個場景只要一個數(shù)字就可以了,當(dāng)數(shù)量比較大時,一般顯示為"7k" ,"10W" 這樣。

          以文章id為key

          //以文章id=888為例?
          127.0.0.1:6379[2]>?set?star:tid:888?898?//設(shè)置點贊數(shù)量?
          OK?
          127.0.0.1:6379[2]>?incr?star:tid:888?//實現(xiàn)數(shù)量自增?(integer)?
          899


          場景b:點贊去重,避免重復(fù)點贊

          要實現(xiàn)這個需求,必須有文章點贊的uid列表,以uid為key場景c:一般在用戶中心,可以看到用戶自己的點贊列表

          這個需求可以使用場景b的數(shù)據(jù)來實現(xiàn)。

          51843e108bb4a360b6cbbded94537a11.webp

          場景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

          點贊的地方,如果點贊過顯示紅色,沒有則顯示黑白色,

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

          如下圖,我選了一條熱點,擁有眾多粉絲的“豬豬”

          6aa1d26780c054effd411e8d93607661.webp

          可能有人覺得,點贊列表沒人關(guān)心,存儲又會浪費大量資源,不如不存!但是,這個數(shù)據(jù)是必須要有的。兩點:

          • 去重。點贊數(shù)可以不精確,但去重必須是精確的,

          • 另外一個社交產(chǎn)品,用戶行為的一點一滴都需要記錄,對于后續(xù)的用戶行為分析和數(shù)據(jù)挖掘都是有意義的。

          上面使用string存儲的用戶點贊數(shù)量,除了string,還可以用hash來存儲,對文章id分塊,每100個存到一個hash,分別存入hash table,每個文章id為hash的一個key,value存儲點贊的用戶id,如果點贊用戶很多,避免id過多產(chǎn)生性能問題,可以單列出來,用sorted set結(jié)構(gòu)保存,熱點的畢竟是少數(shù)。

          3f024964b03f45bf21a2b28b1476bdce.webp

          方案優(yōu)缺點比對

          hash:使用了更少的全局key ,節(jié)省了內(nèi)存空間;但是也帶來了問題

          如何根據(jù)文章id路由到對應(yīng)的hash?

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

          使用hash雖然節(jié)省了空間,但增加了復(fù)雜度,如何選擇就看個人需求了。

          除此之外,你還有其他的方法嗎?

          3. 數(shù)據(jù)一致性

          redis作為storage使用時,一定要做好數(shù)據(jù)的持久化,必須開啟 rdb 和 aof,這會導(dǎo)致業(yè)務(wù)只能使用一半的機器內(nèi)存,所以要做好容量的監(jiān)控,及時擴容。

          另外只要有數(shù)據(jù)copy,就會有一致性問題,這就是另外一個很重要的話題了。以后有時間再細聊吧!

          往期推薦

          為什么國內(nèi)流行的 MyBatis ,國外 Java 工程師卻不愿意使用?

          盤點開發(fā)中那些常用的MySQL優(yōu)化

          Spring 中 @Component、@Service 等注解如何被解析?

          Redis 的內(nèi)存淘汰策略問題

          Redis 6.0 除了多線程,別忘了這個牛逼特性!

          JDK 14 里的調(diào)試神器了解一下?


          掃一掃,關(guān)注我

          一起學(xué)習(xí),一起進步

          瀏覽 28
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久国产黄色视频 | 青青操手机在线观看 | 高潮毛片77777777毛片 | 亚洲女同在线 | 豆花视频无码在线看 |