評論系統的設計
文章或者視頻一般都有評論模塊,因爲評論不僅可以增強用戶的參與度、促進交流,而且通過用戶的各種精彩評論與回覆增加了內容吸引力,所以文章或者視頻下的評論是非常重要的一個板塊,今天我們來聊聊評論模塊的設計。
1、基礎設計
如下是一個文章的評論截圖:
通過上圖的評論圖我們發現用戶發表了一級評論之後,其他的用戶可以在這個一級評論上繼續評論成爲二級評論,多個二級評論不用一次性展示,只展示二級評論的數量。
用戶可以繼續在二級評論的基礎上再次評論成爲三級評論,如果多個三級評論只展示三級評論的數量,如下如所示:
針對上圖的評論圖我們設計數據表字段。在評論中針對不同的主題(文章或者視頻)我們有一個主題表,主題表主要的字段如下設計:
主題表爲了做到通用,我們設計 type 來區分不同的內容來源;主題表中設計一個 count 字段主要的意義在於一個精彩的內容會有多個用戶對這個主題進行評論,爲了展示評論總數量,我們設計了此字段,這樣就不用在查詢所有的評論總數量,如下所示的效果圖:
如果對某個一級評論的二級評論數量過多,此時只展示剩餘二級評論的數量,當用戶點擊這個數字之後我們再去查詢具體的評論信息。
因爲評論內容可能會很多,所以我們考慮將內容和索引表分開,目的是減少 mysql 一次查詢所佔用的內存開銷。設計的索引表和內容表如下所示:
數據表設計出來之後,我們如何支持到樓中樓(一級評論下有二級評論,二級評論下有三級評論),如何支持多個下級評論只展示數量呢?如下的評論表的關聯關係圖:
(a)root = 0 表示當前是一個根評論(一級評論),當前的一級評論存在二級,一級評論的 id 作爲二級評論的 parentId 和 root,同樣道理,二級評論下的三級評論一樣的方式來關聯。每級評論上都要記錄下級評論的數量(就是 count 字段的值)目的是用來給前端展示剩餘的下級評論數量。
(b)root > 0 表示的當前爲非根評論(一級評論),通過 root 我們可以找到這個評論歸屬於哪個根評論。
上面分析樓中樓評論的存儲方案,現在如何讀取評論數據呢?如下圖所所以的一個簡單的多級評論圖:
一級評論(root=0)的 id 關聯下屬的所有下級評論,我們通過一級評論的 id 關聯二級評論的 parentId,這樣我們就可以查詢到所有的一級評論下的二級評論,同樣的二級評論的 id 作爲三級評論的 parentId,這樣就可以找到二級評論下的所有三級評論。這樣針對複雜的樓中樓評論我們就可以設計出來了。
2、保存評論
(1)用戶通過客戶端發出寫入評論的請求,請求通過 nignx 和網關層轉發到評論服務上,爲了提高評論服務響應速度和支持高併發,我們採用異步的 MQ 的方式寫入評論,也就是請求到了評論服務之後,評論服務發送一條評論寫入的 MQ 消息。
(2)消息服務開啓多線程消費 MQ 消息,將評論的數據寫入到數據庫中。
(3)消費完畢之後採用服務端主動推送寫入成功的評論到客戶端展示。
(4)評論寫入數據庫成功之後,我們通過 canal 的方式將數據同步到 es 中,這樣運營人員可以通過 es 查詢和管理評論。
3、高併發下評論系統的優化
在高併發下,評論系統的需要做優化的應對大流量的衝擊,如下的一些常見手段:
(1)緩存熱點評論
通過定時任務定期從數據庫中提取最受歡迎的熱點評論,然後加載到 Redis 中。這樣用戶在訪問這些評論時,系統可以直接從緩存中讀取,而不必每次都去查詢數據庫。同時爲了避免緩存中的數據長期不更新,我們可以設置緩存的失效時間,緩存中的評論過期後重新加載新的熱點評論。
(2)評論數據讀寫分離
讀寫分離適用於讀操作遠多於寫操作的場景。在評論系統中,讀操作遠比寫操作頻繁,所以通過讀寫分離來提升系統的讀取性能。
普通評論的讀取操作分配到從庫中,避免主庫負擔過重,同時結合熱點評論緩存的方式,可以有效地減少數據庫的讀取壓力,提高系統的響應速度。
(3)評論異步寫入
評論數據不直接寫入到數據路中,而是採用異步 MQ 的方式寫入到數據庫中,這樣可以大大的提高系統的響應速度。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/s5su6JuW0ex9o1vXxtKaDQ