分類樹查詢性能優化:從 2 秒到 0.1 秒的技術蛻變之路

在電商系統中,分類樹查詢是一個基礎且高頻的功能,然而這個看似簡單的功能背后卻隱藏著不小的性能挑戰。本文將分享我們在實際項目中對分類樹查詢功能進行五次優化的全過程,看如何將查詢耗時從 2 秒縮短至 0.1 秒,為用戶提供更流暢的體驗。

一、初始版本:從數據庫直接查詢

我們的項目采用 Spring Boot 框架,前端使用 Thymeleaf 模板引擎進行動態渲染。在項目初期,為了快速開發功能,分類樹查詢接口直接從數據庫中查詢分類數據,組裝成分類樹后返回給前端。

這種簡單直接的方式雖然快速實現了功能,但隨著分類數據的不斷增加,性能問題很快暴露出來。在開發環境中,當分類數量較多時,接口響應時間逐漸變長,甚至達到了 2 秒,嚴重影響了用戶體驗。

二、第一次優化:引入 Redis 緩存

面對性能瓶頸,我們首先想到的是添加 Redis 緩存。優化后的流程如下:

  1. 用戶訪問接口獲取分類樹時,先從 Redis 中查詢數據。
  2. 如果 Redis 中有數據,直接返回。
  3. 如果 Redis 中沒有數據,從數據庫中查詢數據,拼接成分類樹返回。
  4. 將從數據庫中查到的分類樹數據保存到 Redis 中,設置過期時間為 5 分鐘。

通過這種方式,大部分請求可以直接從 Redis 中獲取數據,減少了數據庫的訪問壓力。經過測試,開發環境的接口響應時間得到了明顯改善,聯調和自測順利完成。

三、第二次優化:異步定期更新緩存

將功能部署到測試環境后,初期測試沒有發現問題,但隨著測試的深入,隔一段時間就會出現首頁訪問很慢的情況。分析發現,當 Redis 緩存過期時,大量請求同時訪問數據庫,導致數據庫壓力過大,從而影響了性能。

為了解決這個問題,我們決定使用 Job 定期異步更新分類樹到 Redis 中。具體優化措施如下:

  1. 增加一個 Job,每隔 5 分鐘執行一次,從數據庫中查詢分類數據,封裝成分類樹,更新到 Redis 緩存中。
  2. 保留原來的分類樹同步寫入 Redis 的邏輯,以防止 Redis 突然掛掉。
  3. 將 Redis 的過期時間改為永久。

這次優化后,測試環境再也沒有出現分類樹查詢的性能問題。

四、第三次優化:添加內存緩存

在網站即將上線前,我們對首頁進行了壓力測試,發現最大 QPS 只有 100 多,性能瓶頸依然存在。經過分析,我們發現每次都從 Redis 獲取分類樹是導致性能問題的主要原因。

于是,我們決定添加內存緩存。考慮到分類數據更新頻率較低,即使不同服務器節點的內存緩存數據存在短暫的不一致,也不會對用戶造成太大影響,因此選擇使用 Spring 推薦的 Caffeine 作為內存緩存。優化后的流程如下:

  1. 用戶訪問接口時,先從本地內存緩存中查詢分類樹數據。
  2. 如果本地緩存有數據,直接返回。
  3. 如果本地緩存沒有數據,從 Redis 中查詢數據。
  4. 如果 Redis 中有數據,將數據更新到本地緩存中,然后返回。
  5. 如果 Redis 中也沒有數據(說明 Redis 掛了),從數據庫中查詢數據,更新到 Redis 中,然后更新到本地緩存中,返回數據。
  6. 設置本地緩存的過期時間為 5 分鐘,以便獲取新的數據。

這次優化效果顯著,再次進行壓力測試時,QPS 提升到了 500 多,滿足了上線要求。

五、第四次優化:開啟 GZip 壓縮

使用了很長一段時間都沒有出現問題。但兩年后的一天,有用戶反饋網站首頁有點慢。經過排查,我們發現分類樹的數據已經增加到了上萬個,一次性返回的數據量太大,導致網絡傳輸耗時較長。

針對這個問題,我們想到了開啟 Nginx 的 GZip 功能,讓數據在傳輸之前先進行壓縮。之前調用接口返回的分類樹數據大小為 1MB,開啟 GZip 壓縮后,數據大小縮小到了 100KB,一下子縮小了 10 倍,性能得到了明顯提升。

六、第五次優化:優化 Redis 存儲

在一次 Redis 大 key 排查中,分類樹數據被揪了出來。原來,我們一直使用簡單的 key/value 結構在 Redis 中保存分類樹數據,隨著分類數量的增加,這個 value 變得越來越大,成為了 Redis 中的大 key,影響了 Redis 的性能。

為了解決這個問題,我們從以下幾個方面進行了優化:

  1. 數據瘦身:只保存需要用到的字段,去除了如 inDate、inUserId 和 inUserName 等不必要的字段。
  2. 修改字段名稱:在 JSON 序列化時,將字段名稱改為簡短的名稱,減少數據量。例如,將 id 改為 i,name 改為 n 等。
  3. 數據壓縮:使用 GZip 工具類將 JSON 字符串壓縮成 byte 數組,然后保存到 Redis 中。獲取數據時,再將 byte 數組解壓并轉換成 JSON 字符串。

例如

@AllArgsConstructor
@Data
public class Category {private Long id;private String name;private Long parentId;private Date inDate;private Long inUserId;private String inUserName;private List<Category> children;
}

例如

@AllArgsConstructor
@Data
public class Category {/*** 分類編號*/@JsonProperty("i")private Long id;/*** 分類層級*/@JsonProperty("l")private Integer level;/*** 分類名稱*/@JsonProperty("n")private String name;/*** 父分類編號*/@JsonProperty("p")private Long parentId;/*** 子分類列表*/@JsonProperty("c")private List<Category> children;
}

經過這些優化,保存到 Redis 中的分類樹數據大小減少了 10 倍,成功解決了 Redis 的大 key 問題。

七、優化成果總結

通過這五次優化,分類樹查詢的性能得到了顯著提升:

  • 初始版本:響應時間約 2 秒
  • 最終版本:響應時間約 0.1 秒
  • QPS 從 100 多提升到 500 多
  • 數據傳輸量從 1MB 減少到 100KB 左右
  • Redis 中的數據存儲量減少了 10 倍

八、經驗啟示

  1. 性能優化是一個持續的過程:隨著業務的發展和數據量的增加,原來的優化措施可能會逐漸失效,需要持續關注性能問題并進行優化。
  2. 緩存策略的選擇很重要:根據數據的特點和業務需求,選擇合適的緩存策略,如 Redis 緩存、內存緩存等,并合理設置緩存過期時間。
  3. 數據壓縮不容忽視:在數據傳輸和存儲過程中,合理使用數據壓縮技術可以有效減少數據量,提高性能。
  4. 數據庫操作要謹慎:數據庫是系統的瓶頸之一,應盡量減少對數據庫的訪問,避免大量并發請求同時訪問數據庫。
  5. 代碼優化細節決定成敗:在實際開發中,一些看似微小的優化,如字段名稱的簡化、不必要字段的去除等,累積起來也能帶來顯著的性能提升。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/90357.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/90357.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/90357.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ansible 介紹及安裝

簡介 Ansible 是一款開源的自動化工具&#xff0c;廣泛應用于配置管理、應用部署、任務自動化以及多節點管理等領域。它由 Michael DeHaan 于 2012 年創建&#xff0c;ansible 目前已經已經被紅帽官方收購&#xff0c;是自動化運維工具中大家認可度最高的&#xff0c;并且上手…

超光譜相機的原理和應用場景

超光譜相機是光譜成像技術的尖端形態&#xff0c;具備亞納米級光譜分辨率與超千波段連續覆蓋能力&#xff0c;通過“圖譜合一”的三維數據立方體實現物質的精準識別與分析。其核心技術架構、應用場景及發展趨勢如下&#xff1a;一、核心技術原理1、?分光機制??干涉分光?&am…

掌握MySQL函數:高效數據處理指南

? 在 MySQL 數據庫管理系統中&#xff0c;函數扮演著極為重要的角色。它們就像是數據庫操作的得力助手&#xff0c;能夠幫助開發者高效地完成各種數據處理任務。本文將深入探討 MySQL 函數的方方面面&#xff0c;從其基本概念到實際應用&#xff0c;幫助讀者全面掌握這一強大的…

10.SpringBoot的統一異常處理詳解

文章目錄1. 異常處理基礎概念1.1 什么是異常處理1.2 為什么需要統一異常處理1.3 Spring異常處理機制2. SpringBoot默認異常處理2.1 默認錯誤頁面2.2 自定義錯誤頁面3. 全局異常處理器3.1 基礎全局異常處理器3.2 統一響應格式3.3 使用統一響應格式的異常處理器4. 自定義異常4.1 …

No Hack No CTF 2025Web部分個人WP

No Hack No CTF 2025 Next Song is 春日影 hint&#xff1a;NextJS Vulnerability at /adminCVE-2025-29927Next.js 中間件權限繞過漏洞 訪問admin路由發現跳轉利用CVE&#xff1a; curl -i \-H "x-middleware-subrequest: middleware:middleware:middleware:middleware:m…

STM32第十八天 ESP8266-01S和電腦實現串口通信

一&#xff1a; ESP和電腦實現串口通信1. 配置 WiFi 模式 ATCWMODE3 // softAPstation mode 響應 : OK 2. 連接路路由器? ATCWJAP"SSID","password" // SSID and password of router 響應 : OK 3. 查詢 ESP8266 設備的 IP 地址 ATCIFSR 響應 : CIFSR:APIP…

STM32第十七天ESP8266-01Swifi模塊

ESP8266-01S wifi模塊1&#xff1a;ESP8266是實現wifi通訊的一個模塊種類&#xff0c;有很多分類包含esp8266-12、esp8266-12E、ESP8266-01S、esp32等等。esp8266-01S由一顆esp8266作為主控再由一塊flash作為存儲芯片組成&#xff0c;帶有板載芯片供電采用3.3V電壓使用串口進行…

ProCCD復古相機:捕捉復古瞬間

在數字攝影盛行的今天&#xff0c;復古膠片相機的獨特質感和懷舊風格依然吸引著眾多攝影愛好者。ProCCD復古相機APP正是這樣一款能夠滿足用戶對復古攝影需求的應用程序。它通過模擬復古CCD數碼相機的效果&#xff0c;讓用戶在手機上也能輕松拍出具有千禧年風格的照片和視頻。無…

Spring Boot 應用啟動時,端口 8080 已被其他進程占用,怎么辦

1、修改application.yml配置文件&#xff0c;將端口號更改為未被占用的端口&#xff08;例如9090&#xff09;2、以管理員身份運行命令提示符在命令提示符窗口中輸入命令netstat -ano | findstr :8080”輸出結果可能如下&#xff1a;“TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING xx…

使用Jenkins完成springboot項目快速更新

?重磅&#xff01;盹貓的個人小站正式上線啦&#xff5e;誠邀各位技術大佬前來探秘&#xff01;? 這里有&#xff1a; 硬核技術干貨&#xff1a;編程技巧、開發經驗、踩坑指南&#xff0c;帶你解鎖技術新姿勢&#xff01;趣味開發日常&#xff1a;代碼背后的腦洞故事、工具…

HDLBits刷題筆記和一些拓展知識(九)

文章目錄HDLBits刷題筆記CircuitsFsm1Fsm1sFsm2Fsm3onehotExams/ece241 2013 q4Lemmings1Lemmings2Lemmings3Lemmings4Fsm onehotFsm ps2Fsm ps2dataFsm serialFsm serialdataFsm serialdpFsm hdlc未完待續HDLBits刷題筆記 以下是在做HDLBits時的一些刷題筆記&#xff0c;截取一…

CD46.【C++ Dev】list的模擬實現(1)

目錄 1.STL庫的list 2.模擬實現 節點結構體 list類 無參構造函數 尾插函數 迭代器★ begin() operator 前置 后置 operator-- 前置-- 后置-- operator! operator end() operator* const修飾的迭代器的設計 1.STL庫的list 模擬實現list之前,先看看STL庫里的…

數據結構——二叉樹的基本介紹

————————————本文旨在討論與學習計算機知識&#xff0c;歡迎交流————————————上一章&#xff0c;我們講解了樹結構的綜述導論&#xff0c;那么&#xff0c;現在我們來深入了解一下樹結構中最常用研究的結構——二叉樹結構&#xff08;上一章的擴展——…

英偉達發布 Llama Nemotron Nano 4B:專為邊緣 AI 和科研任務優化的高效開源推理模型

英偉達推出了 Llama Nem)otron Nano 4B&#xff0c;這是一款專為在科學任務、編程、符號運算、函數調用和指令執行方面提供強大性能與效率而設計的開源推理模型&#xff0c;其緊湊程度足以支持邊緣部署。該模型僅包含 40 億參數&#xff0c;卻在內部基準測試中實現了比其他多達…

論文閱讀筆記——Autoregressive Image Generation without Vector Quantization

MAR 論文 基于 VQ&#xff08;向量量化&#xff09;的圖像生成方法具有顯著優勢&#xff0c;它通過離散化壓縮將原始圖像映射到有限的 codebook 空間&#xff0c;從而縮小學習范圍、降低建模難度&#xff0c;同時這種離散表示更易于與自回歸&#xff08;AG&#xff09;生成方式…

【科普】關于C 語言日志系統實戰:如何同時輸出到終端和文件?

1.概述 c語言沒有現成的日志庫&#xff0c;如果要記錄日志&#xff0c;需要自己封裝一個日志庫。如果要實現日志級別和參數打印&#xff0c;還是比較麻煩的&#xff0c;正好在github找到了一個c語言開源日志庫&#xff0c;可以實現日志級別打印&#xff0c;參數打印&#xff0…

2025,數字人借直播場景邁過“真假線”丨數智化觀察

作者 | 曾響鈴文 | 響鈴說一夜帶貨超5500萬GMV、觀看人次1300萬&#xff0c;羅永浩數字人在百度電商的直播首秀正在掀起新的行業浪潮——2025&#xff0c;數字人直播帶貨成功出圈&#xff0c;加速進入大眾視野&#xff0c;被更多的消費者所認可。成就這場熱潮的關鍵點之一&…

HTML表格導出為Excel文件的實現方案

1、前端javascript可通過mime類型、blob對象或專業庫&#xff08;如sheetjs&#xff09;實現html表格導出excel&#xff0c;適用于中小型數據量&#xff1b;2、服務器端方案利用后端語言&#xff08;如python的openpyxl、java的apache poi&#xff09;處理復雜報表和大數據&…

企業微信iPad協議端強制拉群漏洞深度分析

正常一次最多邀請40人進群 超過40人的拉群&#xff0c;會變成邀請&#xff0c;需要對方同意 新版本修復了漏洞&#xff0c;但還是可以用老版本進行強制拉群 雖然官方也做了版本過低的限制&#xff0c;但還是有辦法繞過 要么修改版本號或者登錄幾天新版本&#xff0c;之后就可以…

Python編譯器(Pycharm Jupyter)

Pycharm下載不過多贅述pycharm導入anaconda創建的python環境選擇想要的環境 Jupyter Jupyter 是一個開源的交互式計算環境&#xff0c;能夠讓用戶將代碼、文本&#xff08;包括 Markdown&#xff09;、可視化結果等內容整合在一個文檔中&#xff0c;非常適合進行數據分析、科學…