日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

为什么超长列表数据的翻页技术实现复杂(二)

發(fā)布時(shí)間:2025/3/17 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 为什么超长列表数据的翻页技术实现复杂(二) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??

上文為什么超長(zhǎng)列表數(shù)據(jù)的翻頁(yè)技術(shù)實(shí)現(xiàn)復(fù)雜提到了超長(zhǎng)列表翻頁(yè)技術(shù)設(shè)計(jì)上一些問(wèn)題,今天討論下部分解決思路。

前新浪同事 @pi1ot 最近在程序員雜志發(fā)表的一篇文章《門戶級(jí)UGC系統(tǒng)的技術(shù)進(jìn)化路線》也是超長(zhǎng)列表的一個(gè)經(jīng)典案例,在正式展開(kāi)思路之前,我們也不妨了解一下此文所說(shuō)新浪評(píng)論系統(tǒng)的演進(jìn)思路。

從文中看到幾個(gè)版本的列表翻頁(yè)實(shí)現(xiàn)方案

3.0版

3.0系統(tǒng)的緩存模塊設(shè)計(jì)的比較巧妙,以顯示頁(yè)面為單位緩存數(shù)據(jù),因?yàn)樵u(píng)論頁(yè)面是依照提交時(shí)間降序排列,每新增一條新評(píng)論,所有帖子都需要向下移動(dòng)一位,所以緩存格式設(shè)計(jì)為每?jī)身?yè)數(shù)據(jù)一個(gè)文件,前后相鄰的兩個(gè)文件有一頁(yè)的數(shù)據(jù)重復(fù),最新的緩存文件通常情況下不滿兩頁(yè)數(shù)據(jù)。

此方案由于每頁(yè)的條數(shù)是定長(zhǎng)的,因此主要采用緩存所有列表的方案。但為了數(shù)據(jù)更新的便利,緩存結(jié)構(gòu)比較復(fù)雜。從今天多年之后的眼光來(lái)看,這種設(shè)計(jì)不利于理解、擴(kuò)展及維護(hù)。因此目前大多不傾向使用這種方案。

4.0版

解決方案是在MySQL數(shù)據(jù)庫(kù)和頁(yè)面緩存模塊之間,新建一個(gè)帶索引的數(shù)據(jù)文件層,每條新聞的所有評(píng)論都單獨(dú)保存在一個(gè)索引文件和一個(gè)數(shù)據(jù)文件中,期望通過(guò)把對(duì)數(shù)據(jù)庫(kù)單一表文件的讀寫(xiě)操作,分解為文件系統(tǒng)上互不干涉可并發(fā)執(zhí)行的讀寫(xiě)操作,來(lái)提高系統(tǒng)并發(fā)處理能力。在新的索引數(shù)據(jù)模塊中,查詢?cè)u(píng)論總數(shù)、追加評(píng)論、更新評(píng)論狀態(tài)都是針對(duì)性優(yōu)化過(guò)的高效率操作。從這時(shí)候起,MySQL數(shù)據(jù)庫(kù)就降到了只提供歸檔備份和內(nèi)部管理查詢的角色,不再直接承載任何用戶更新和查詢請(qǐng)求了。

使用自定義索引的方式,由于未與相關(guān)人員交流細(xì)節(jié),推斷應(yīng)該是類似數(shù)組的結(jié)構(gòu)。

從上述案例看到,評(píng)論系統(tǒng)是一種典型的超長(zhǎng)列表數(shù)據(jù)結(jié)構(gòu),如果再M(fèi)ySQL的基礎(chǔ)上來(lái)做,需要設(shè)計(jì)額外的索引結(jié)構(gòu)來(lái)實(shí)現(xiàn)高效的翻頁(yè)功能

由于超長(zhǎng)列表的翻頁(yè)實(shí)現(xiàn)成本高主要是由于列表索引的B-TREE結(jié)構(gòu)方面原因,B-TREE結(jié)構(gòu)能快速查找到某個(gè)key,但不是為葉子節(jié)點(diǎn)的Range訪問(wèn)而設(shè)計(jì),因此主要解決思路也是圍繞B-TREE的range訪問(wèn)而進(jìn)行優(yōu)化。

首先、從原理來(lái)看,可以在B-TREE增加以下2個(gè)二級(jí)索引字段:

  • Count index?記錄每個(gè)非葉子節(jié)點(diǎn)下的條目數(shù),這樣可以幫助快速定位到任意的offset;
  • Offset index?記錄部分葉子節(jié)點(diǎn)的offset,比如每隔1000個(gè)id記錄一個(gè)offset如下,并保存在另外一個(gè)列表中,當(dāng)需要查找某個(gè)offset的時(shí)候,則可以利用附近已經(jīng)記錄offset的id來(lái)定位目的地位置。比如當(dāng)翻頁(yè)到1010時(shí),如果offset index記錄了[1000: id10345],則可以從id10345往后10個(gè)元素找到10010。
[ {"1000":10345}, {"2000":13456}, {"3000":22345}, {"4000":56789}, {"5000":66788} ]

這2個(gè)字段可以同時(shí)使用,也可以只用其中一個(gè)。如圖

再看如何將上述方法應(yīng)用到具體的實(shí)現(xiàn)中。由于本文主要討論MySQL環(huán)境,MySQL要在B-TREE上額外保存一些信息需要修改MySQL源代碼,修改門檻較高,因此更簡(jiǎn)單方法是將上述二級(jí)索引通過(guò)應(yīng)用層保存在另外的表中。

一種非嚴(yán)格意義的count index實(shí)現(xiàn)如下:

CREATE TABLE IF NOT EXISTS `second_index` (`id` int(11) NOT NULL AUTO_INCREMENT,`uid` int(11) NOT NULL,`yymm` int(11) NOT NULL,`index_count` int(11) NOT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO `second_index` (`id`, `uid`, `yymm`, `index_count`) VALUES (1, 1, 1409, 123), (2, 1, 1410, 2342), (3, 1, 1411, 534), (4, 1, 1412, 784), (5, 1, 1501, 845);

一種offset index實(shí)現(xiàn)如下:
在第一次用戶翻頁(yè)到某個(gè)offset位置時(shí),在redis直接保存offset, id。當(dāng)有其他請(qǐng)求來(lái)查找offset之后數(shù)據(jù)時(shí),可以從offset的位置往后掃描。如果列表的數(shù)據(jù)發(fā)生了變化,需要及時(shí)將Redis保存的offset index刪除。

以上2種方法已經(jīng)在生產(chǎn)環(huán)境使用。

@icycrystal4 對(duì)此文所提方法亦有貢獻(xiàn)。

轉(zhuǎn)載于:https://my.oschina.net/boltwu/blog/424231

總結(jié)

以上是生活随笔為你收集整理的为什么超长列表数据的翻页技术实现复杂(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。