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

          帖子中心,1億數(shù)據(jù),架構(gòu)如何設(shè)計?

          共 3656字,需瀏覽 8分鐘

           ·

          2020-07-30 18:17

          帖子中心,是互聯(lián)網(wǎng)業(yè)務(wù)中,一類典型的“1對多”業(yè)務(wù),即:一個用戶能發(fā)布多個帖子,一個帖子只有一個發(fā)布者。


          隨著數(shù)據(jù)量的逐步增大,并發(fā)量的逐步增大,帖子中心這種“1對多”業(yè)務(wù),架構(gòu)應(yīng)該如何設(shè)計,有哪些因素需要考慮,是本文將要系統(tǒng)性討論的問題。


          什么是x對x?

          所謂的“1對1”,“1對多”,“多對多”,來自數(shù)據(jù)庫設(shè)計中的“實體-關(guān)系”ER模型,用來描述實體之間的映射關(guān)系。


          什么是“1對1”業(yè)務(wù)?

          用戶中心,一個用戶只有一個登錄名,一個登錄名只對應(yīng)一個用戶,這是典型的1對1業(yè)務(wù)。


          什么是“1對多”業(yè)務(wù)?

          帖子中心,一個用戶可以發(fā)多條微博,一條微博只有一個發(fā)送者,這是典型的1對多業(yè)務(wù)。


          什么是“多對多”業(yè)務(wù)?

          feed關(guān)注,一個用戶可以關(guān)注多個用戶,一個用戶也可以被多個用戶關(guān)注,這是典型的多對多業(yè)務(wù)。


          帖子中心是個什么業(yè)務(wù),有什么典型的業(yè)務(wù)需求?

          帖子中心是一個典型的1對多業(yè)務(wù)。


          一個用戶可以發(fā)布多個帖子,一個帖子只對應(yīng)一個發(fā)布者。


          任何脫離業(yè)務(wù)的架構(gòu)設(shè)計都是耍流氓,先來看看帖子中心對應(yīng)的業(yè)務(wù)需求。


          帖子中心,是一個提供帖子發(fā)布,修改,刪除,查看,搜索的服務(wù)。


          帖子中心,有什么寫操作?

          (1)發(fā)布(insert)帖子;

          (2)修改(update)帖子;

          (3)刪除(delete)帖子;


          帖子中心,有什么讀操作?

          (1)通過tid查詢(select)帖子實體,單行查詢

          (2)通過uid查詢(select)用戶發(fā)布過的帖子,列表查詢

          (3)帖子檢索(search),例如通過時間、標題、內(nèi)容搜索符合條件的帖子;


          在數(shù)據(jù)量較大,并發(fā)量較大的時候,架構(gòu)如何設(shè)計?

          典型的,通常通過元數(shù)據(jù)與索引數(shù)據(jù)分離的架構(gòu)設(shè)計方法。

          架構(gòu)中的幾個關(guān)鍵點,如上圖所示:

          (1)tiezi-center:帖子服務(wù);

          (2)tiezi-db:提供元數(shù)據(jù)存儲;

          (3)tiezi-search:帖子搜索服務(wù);

          (4)tiezi-index:提供索引數(shù)據(jù)存儲;

          (5)MQ:tiezi-center與tiezi-search通訊媒介,一般不直接使用RPC調(diào)用,而是通過MQ對兩個子系統(tǒng)解耦。


          此時,讀需求怎么滿足?

          tiezi-center和tiezi-search分別滿足兩類不同的讀需求。

          如上圖所示:

          (1)tid和uid上的查詢需求,可以由tiezi-center從元數(shù)據(jù)讀取并返回;

          (2)其他類檢索需求,可以由tiezi-search從索引數(shù)據(jù)檢索并返回;


          寫需求怎么辦呢?

          至于寫需求,如上圖所示:

          (1)增加,修改,刪除的操作都會從tiezi-center發(fā)起;

          (2)tiezi-center修改元數(shù)據(jù);

          (3)tiezi-center將信息修改通知發(fā)送給MQ;

          (4)tiezi-search從MQ接受修改信息;

          (5)tiezi-search修改索引數(shù)據(jù);


          tiezi-search,搜索架構(gòu)不是本文的重點,不再展開,后文將重點描述帖子中心元數(shù)據(jù)水平切分設(shè)計。


          帖子中心,數(shù)據(jù)庫元數(shù)據(jù)如何設(shè)計?

          帖子中心業(yè)務(wù),很容易了解到,其核心元數(shù)據(jù)為:

          t_tiezi(tid, uid, time, title, content, …);

          其中:

          (1)tid為帖子ID,主鍵;

          (2)uid為用戶ID,發(fā)帖人;

          (3)time, title, content …等為帖子屬性;


          數(shù)據(jù)庫設(shè)計上,在業(yè)務(wù)初期,單庫就能滿足元數(shù)據(jù)存儲要求

          (1)tiezi-center:帖子中心服務(wù),對調(diào)用者提供友好的RPC接口;

          (2)tiezi-db:對帖子數(shù)據(jù)進行存儲;


          在相關(guān)字段上建立索引,就能滿足相關(guān)業(yè)務(wù)需求

          (1)帖子記錄查詢,通過tid查詢,約占讀請求量90%;

          select * from t_tiezi where tid=$tid

          (2)帖子列表查詢,通過uid查詢其發(fā)布的所有帖子,約占讀請求量10%;

          select * from t_tiezi where uid=$uid


          隨著數(shù)據(jù)量越來越大,如何進行水平切分,對存儲容量進行線性擴展呢?


          方案一:帖子ID切分法


          既然是帖子中心,并且帖子記錄查詢量占了總請求的90%,很容易想到通過tid字段取模來進行水平切分。

          這個方法簡單直接,優(yōu)點:

          (1)100%寫請求可以直接定位到庫;

          (2)90%的讀請求可以直接定位到庫;


          缺點也很明顯:

          (1)一個用戶發(fā)布的所有帖子可能會落到不同的庫上,10%的請求通過uid來查詢會比較麻煩;

          如上圖,一個uid訪問需要遍歷所有庫


          有沒有一種切分方法,確保同一個用戶發(fā)布的所有帖子都落在同一個庫上,而在查詢一個用戶發(fā)布的所有帖子時,不需要去遍歷所有的庫呢?


          方案二:用戶ID切分法


          使用uid來分庫可以解決這個問題。


          新的問題出現(xiàn)了:如果使用uid來分庫,確保了一個用戶的帖子數(shù)據(jù)落在同一個庫上,那通過tid來查詢,就不知道這個帖子落在哪個庫上了,豈不是還需要遍歷全庫,需要怎么優(yōu)化呢?


          tid的查詢是單行記錄查詢,只要在數(shù)據(jù)庫(或者緩存)記錄tid到uid的映射關(guān)系,就能解決這個問題。


          新增一個索引庫:

          t_mapping(tid, uid);

          (1)這個庫只有兩列,可以承載很多數(shù)據(jù);

          (2)即使數(shù)據(jù)量過大,索引庫可以利用tid水平切分;

          (3)這類kv形式的索引結(jié)構(gòu),可以很好的利用cache優(yōu)化查詢性能;

          (4)一旦帖子發(fā)布,tid和uid的映射關(guān)系就不會發(fā)生變化,cache的命中率會非常高;


          使用uid分庫,并增加索引庫記錄tid到uid的映射關(guān)系之后,每當(dāng)有uid上的查詢,可以通過uid直接定位到庫。


          每當(dāng)有tid上的查詢,可以先查mapping表得到uid,再通過uid定位到庫。


          這個方法的優(yōu)點是:

          (1)一個用戶發(fā)布的所以帖子落在同一個庫上;

          (2)10%的請求過過uid來查詢列表,可以直接定位到庫;

          (3)索引表cache命中率非常高,因為tid與uid的映射關(guān)系不會變;


          缺點也很明顯:

          (1)90%的tid請求,以及100%的修改請求,不能直接定位到庫,需要先進行一次索引表的查詢,當(dāng)然這個查詢非常塊,通常在5ms內(nèi)可以返回;

          (2)數(shù)據(jù)插入時需要操作元數(shù)據(jù)與索引表,可能引發(fā)潛在的一致性問題;


          有沒有一種方法,既能夠通過uid定位到庫,又不需要建立索引表來進行二次查詢呢,使得uid和tid都能夠直接一次命中的方案呢?


          方案三:基因法


          什么是分庫基因?

          通過uid分庫,假設(shè)分為16個庫,采用uid%16的方式來進行數(shù)據(jù)庫路由,這里的uid%16,其本質(zhì)是uid的最后4個bit決定這行數(shù)據(jù)落在哪個庫上這4個bit,就是分庫基因


          什么是基因法分庫?

          在“1對多”的業(yè)務(wù)場景,使用“1”分庫,在“多”的數(shù)據(jù)id生成時,id末端加入分庫基因,就能同時滿足“1”和“多”的分庫查詢需求。

          如上圖所示,uid=666的用戶發(fā)布了一條帖子(666的二進制表示為:1010011010):

          (1)使用uid%16分庫,決定這行數(shù)據(jù)要插入到哪個庫中;

          (2)分庫基因是uid的最后4個bit,即1010

          (3)在生成tid時,先使用一種分布式ID生成算法生成前60bit(上圖中綠色部分);

          (4)將分庫基因加入到tid的最后4個bit(上圖中粉色部分);

          (5)拼裝成最終的64bit帖子tid(上圖中藍色部分);


          這般,保證了同一個用戶發(fā)布的所有帖子的tid,都落在同一個庫上,tid的最后4個bit都相同,于是:

          (1)通過uid%16能夠定位到庫;

          (2)通過tid%16也能定位到庫;


          有人要問了,同一個uid發(fā)布的tid落在同一個庫上,會不會出現(xiàn)數(shù)據(jù)不均衡?

          只要uid是均衡的,每個用戶發(fā)布的平均帖子數(shù)是均衡的,每個庫的數(shù)據(jù)就是均衡的。


          又有人要問了,最開始分16庫,分庫基因是4bit,未來要擴充成32庫,分庫基因變成了5bit,那怎么辦?

          需要提前做好容量預(yù)估,例如事先規(guī)劃好5年內(nèi)數(shù)據(jù)增長256庫足夠,就提前預(yù)留8bit基因。


          總結(jié)

          將以“帖子中心”為典型的“1對多”類業(yè)務(wù),在架構(gòu)上,采用元數(shù)據(jù)與索引數(shù)據(jù)分離的架構(gòu)設(shè)計方法:

          (1)帖子服務(wù),元數(shù)據(jù)滿足uid和tid的查詢需求;

          (2)搜索服務(wù),索引數(shù)據(jù)滿足復(fù)雜搜索尋求;


          對于元數(shù)據(jù)的存儲,在數(shù)據(jù)量較大的情況下,有三種常見的切分方法:

          (1)tid切分法,按照tid分庫,同一個用戶發(fā)布的帖子落在不同的庫上,通過uid來查詢要遍歷所有庫;

          (2)uid切分法,按照uid分庫,同一個用戶發(fā)布的帖子落在同一個庫上,需要通過索引表或者緩存來記錄tid與uid的映射關(guān)系,通過tid來查詢時,先查到uid,再通過uid定位庫;

          (3)基因法,按照uid分庫,在生成tid里加入uid上的分庫基因,保證通過uid和tid都能直接定位到庫;


          架構(gòu)師訓(xùn)練營,歡迎來玩

          相關(guān)文章

          用戶中心,1億數(shù)據(jù),架構(gòu)如何設(shè)計?

          瀏覽 47
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  超污视频网站在线观看免费 | 国产高清免费 | 首页国产中文字幕 | 日本亲子乱婬一级A片视频 | 18禁乱伦 |