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

          老弟想自己做個(gè)微信,被我一個(gè)問(wèn)題勸退了。。

          共 3028字,需瀏覽 7分鐘

           ·

          2024-08-08 13:29

          大家好,我是程序員魚(yú)皮。最近老弟小阿巴放暑假,想找點(diǎn)事情做,于是就來(lái)問(wèn)我:老鲏,我想做個(gè)練手項(xiàng)目,有沒(méi)有什么好的建議?

          我說(shuō):練手項(xiàng)目的話(huà),就做個(gè)自己感興趣的唄,想加什么功能就加什么,做起來(lái)會(huì)更舒服~

          小阿巴:Emm,我感興趣的太多了,有沒(méi)有推薦啊?

          我說(shuō):那就想想自己經(jīng)常使用的網(wǎng)站或 APP,選個(gè)對(duì)業(yè)務(wù)流程相對(duì)熟悉的。

          小阿巴思考片刻,一拍腦袋:對(duì)啊,我天天用微信,那我就做個(gè)微信吧!說(shuō)不定之后大家都在用我做的軟件聊天呢?

          我一聽(tīng),不禁暗自驚嘆,沒(méi)想到小伙子年紀(jì)輕輕,野心很大啊!

          我說(shuō):想法不錯(cuò),但想做個(gè)微信這樣的 IM(即時(shí)通訊)項(xiàng)目,可沒(méi)有那么簡(jiǎn)單,你有什么實(shí)現(xiàn)思路么?說(shuō)來(lái)聽(tīng)聽(tīng)?

          小阿巴:微信的核心功能是收發(fā)消息,我可以把用戶(hù) A 發(fā)送的消息保存到數(shù)據(jù)庫(kù)中,用戶(hù) B 進(jìn)入聊天界面時(shí),從數(shù)據(jù)庫(kù)查詢(xún)出發(fā)給他的消息就行。

          我一聽(tīng)這個(gè)回答,就知道以小阿巴目前的水平,想做出微信是不太可能了。。。

          我問(wèn):Emm,暫且不考慮用戶(hù)體驗(yàn)和性能,我們就先實(shí)現(xiàn)基礎(chǔ)功能吧,你會(huì)怎么讓用戶(hù)查看自己的歷史消息呢?

          小阿巴思考片刻,然后嘴角微微上揚(yáng),露出狡黠的笑容:你是不是以為我會(huì)說(shuō)一次性把所有歷史消息全部查出來(lái)?可惜啊老鲏,你把我想的太天真了,用戶(hù)可能有成百上千條歷史消息,全量加載會(huì)很慢,所以我必然會(huì)使用 分頁(yè) 來(lái)查詢(xún)!

          我說(shuō):行,那你打算怎么分頁(yè)呢?

          小阿巴:這還真難不倒我,這幾年我苦練增刪改查,分頁(yè)寫(xiě)得很溜的!紙筆呈上來(lái),看我給你手寫(xiě) SQL:

          select * from message
          where user = '魚(yú)皮'
          limit 020;

          我說(shuō):Emm,老弟啊,聽(tīng)我一句勸,咱先別想著做微信了,先實(shí)現(xiàn)一個(gè)消息管理系統(tǒng)吧。

          小阿巴:怎么說(shuō)?吾 SQL 不亦精乎?

          其實(shí)這也是一道經(jīng)典的場(chǎng)景題:即時(shí)通訊項(xiàng)目中怎么實(shí)現(xiàn)歷史消息的下拉分頁(yè)加載?

          下面魚(yú)皮給大家講解一下。

          如何實(shí)現(xiàn)下拉分頁(yè)加載?

          業(yè)務(wù)場(chǎng)景

          一般在即時(shí)通訊項(xiàng)目(比如聊天室)中,我們會(huì)采用下拉分頁(yè)的方式讓用戶(hù)加載歷史消息記錄。

          區(qū)別于標(biāo)準(zhǔn)分頁(yè)每次只展示當(dāng)前頁(yè)面的數(shù)據(jù),下拉分頁(yè)加載是 增量加載 的模式,每次下拉時(shí)會(huì)請(qǐng)求加載一小部分新數(shù)據(jù),并放到已加載的數(shù)據(jù)列表中,從而形成無(wú)限滾動(dòng)的效果,確保用戶(hù)體驗(yàn)流暢。

          比如用戶(hù)有 10 條消息記錄,以 5 條為單位進(jìn)行分頁(yè),剛進(jìn)入房間時(shí)只會(huì)加載最新的 5 條消息:

          下拉后,會(huì)加載歷史的第 6 - 10 條消息:

          理解了業(yè)務(wù)場(chǎng)景后,再看下實(shí)現(xiàn)方案,為什么不建議使用傳統(tǒng)分頁(yè)實(shí)現(xiàn)下拉加載。

          傳統(tǒng)分頁(yè)的問(wèn)題

          在傳統(tǒng)分頁(yè)中,數(shù)據(jù)通常是 基于頁(yè)碼或偏移量 進(jìn)行加載的。如果數(shù)據(jù)在分頁(yè)過(guò)程發(fā)生了變化,比如插入新數(shù)據(jù)、刪除老數(shù)據(jù),用戶(hù)看到的分頁(yè)數(shù)據(jù)可能會(huì)出現(xiàn)不一致,導(dǎo)致用戶(hù)錯(cuò)過(guò)或重復(fù)某些數(shù)據(jù)。

          舉個(gè)例子,對(duì)于即時(shí)通訊項(xiàng)目,用戶(hù)可能會(huì)持續(xù)收到新的消息。如果按照傳統(tǒng)分頁(yè)基于偏移量加載,第一頁(yè)已經(jīng)加載了第 1 - 5 行的數(shù)據(jù),本來(lái)要查詢(xún)的第二頁(yè)數(shù)據(jù)是第 6 - 10 行(對(duì)應(yīng)的 SQL 語(yǔ)句為 limit 5, 5),數(shù)據(jù)庫(kù)記錄如下:

          結(jié)果在查詢(xún)第二頁(yè)前,突然用戶(hù)又收到了 5 條新消息,數(shù)據(jù)庫(kù)記錄就變成了下面這樣。原本的第一頁(yè),變成了當(dāng)前的第二頁(yè)!

          這樣就導(dǎo)致查詢(xún)出的第二頁(yè)數(shù)據(jù),正好是之前已經(jīng)查詢(xún)出的第一頁(yè)的數(shù)據(jù),造成了消息重復(fù)加載。所以不建議采用這種方法。

          推薦方案 - 游標(biāo)分頁(yè)

          為了解決這種問(wèn)題,可以使用游標(biāo)分頁(yè)。使用一個(gè)游標(biāo)來(lái)跟蹤分頁(yè)位置,而不是基于頁(yè)碼,每次請(qǐng)求從上一次請(qǐng)求的游標(biāo)開(kāi)始加載數(shù)據(jù)。

          一般我們會(huì)選擇數(shù)據(jù)記錄的唯一標(biāo)識(shí)符(主鍵)、時(shí)間戳、或者具有排序能力的字段作為游標(biāo)。比如即時(shí)通訊系統(tǒng)中的每個(gè)消息,通常都有一個(gè)唯一自增的 id,就可以作為游標(biāo)。每次查詢(xún)完當(dāng)前頁(yè)面的數(shù)據(jù)后,可以將最后一條消息記錄的 id 作為游標(biāo)值傳遞給前端(客戶(hù)端)。

          當(dāng)要加載下一頁(yè)時(shí),前端攜帶游標(biāo)值發(fā)起查詢(xún),后端操作數(shù)據(jù)庫(kù)從 id 小于當(dāng)前游標(biāo)值的數(shù)據(jù)開(kāi)始查詢(xún),這樣查詢(xún)結(jié)果就不會(huì)受到新增數(shù)據(jù)的影響。

          對(duì)應(yīng)的 SQL 語(yǔ)句為:

          SELECT * FROM messages
          WHERE id < :cursorId
          ORDER BY id DESC
          LIMIT 5;

          擴(kuò)展知識(shí)

          其實(shí)游標(biāo)分頁(yè)是一種經(jīng)典方案,它的應(yīng)用場(chǎng)景很多,特別適用于增量數(shù)據(jù)加載、大數(shù)據(jù)量的高性能查詢(xún)和處理。除了 IM 系統(tǒng)獲取歷史消息記錄之外,常見(jiàn)場(chǎng)景還有社交媒體信息流、內(nèi)容推薦系統(tǒng)、數(shù)據(jù)遷移備份等等。

          游標(biāo)分頁(yè)還有很多擴(kuò)展知識(shí),篇幅原因就不在這里展開(kāi)了,感興趣的同學(xué)可以在我們的 程序員面試刷題工具 - 面試?guó)?上閱讀。

          最后

          小阿巴聽(tīng)完,長(zhǎng)嘆道:唉,沒(méi)想到光是這么一個(gè)小功能,就把我難住了。

          我說(shuō):你可別這么想。。。難住你的,可不止這一個(gè)小功能啊!想做一個(gè)成熟的 IM 系統(tǒng),除了最基礎(chǔ)的消息發(fā)送和獲取功能外,你得去學(xué)習(xí) WebSocket 實(shí)時(shí)通訊、得考慮到消息收發(fā)的性能、得考慮到消息的順序和一致性、得考慮到消息的存儲(chǔ)成本和安全,等等等等。可沒(méi)那么容易。

          小阿巴:得,那我先去做消息管理系統(tǒng)了!??

          ???? 點(diǎn)擊下方閱讀原文,獲取魚(yú)皮往期編程干貨。

          往期推薦

          魚(yú)皮的原創(chuàng)項(xiàng)目,越來(lái)越豐富了!

          總有壞人想爬我網(wǎng)站的數(shù)據(jù),看我怎么干他!

          看完這個(gè),我直接把 SQL 刷通了

          每天那么多工作,我為什么能做到 "不忘事" ?

          25 屆秋招交流群,限時(shí)開(kāi)放

          我用這個(gè)工具,一分鐘搞定了簡(jiǎn)歷!

          魚(yú)皮的保姆級(jí)寫(xiě)簡(jiǎn)歷指南,免費(fèi)領(lǐng)

          瀏覽 3663
          23點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          23點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  美女扒开腿秘 免费视频 | 欧美亚洲日韩手机在线 | 色色噜噜激情综合久久 | 中文字幕成人免费视频 | sm免费视频 |