分析內部運行機制,教你解決Redis性能問題

摘要:聚焦Redis的性能分析,思考Redis 可以通過哪些機制來提高性能,當性能瓶頸發生的時候,我們又能做出哪些優化策略,最終確保業務系統的穩定運行。

本文分享自華爲雲社區《分析內部運行機制,教你解決Redis性能問題》,作者: 華爲雲社區精選。

Redis是一種鍵值數據庫,有着時延低、性能好、數據結構豐富的特點,常用作緩存、排行榜、計數器、 消息隊列等,是電商秒殺、聊天系統等業務場景中的“熟客”。

作爲一個“緩存中間商”,Redis的性能問題至關重要,一旦發生操作延遲問題,很容易引起連鎖反應。所以本文聚焦Redis的性能分析,從Redis的基本概念出發,瞭解Redis是什麼,它的運行機制,思考Redis可以通過哪些機制來提高性能,當性能瓶頸發生的時候,我們又能做出哪些優化策略,最終確保業務系統的穩定運行。

讀懂Redis:緩存神器原來是這樣工作的

一個網站總有大量的數據是用戶共享的,如果每個用戶都去數據庫查詢,效率就太低了。所以有了新的解決方案:將用戶共享數據緩存到服務器的內存中。

舉個例子,應用程序們從MySQL查詢到的數據,會到Redis這裏登記,後面再需要用的時候,就先查找Redis的緩存,無需返回到MySQL查找。一套流程下來,爲MySQL減輕了不小的負擔,網絡服務的性能顯著提升。

Redis堪稱數據庫屆的萬金油,哪裏需要往哪裏搬,這也得益於它有着豐富的數據結構,以及強大的讀寫性能。

以數據結構爲例,Redis和其他結構化存儲的重要區別便是,它不僅支持字符串,還支持不同類型的抽象數據結構,如列表、映射、集、排序集、HyperLogLogs、位圖、流和空間索引等。那麼Redis是如何做到如此“萬能”的,它支持的這些數據結構又是如何從底層實現呢?《三次給你聊清楚Redis》之Redis是個啥 就從非關係型數據庫談起,詳細聊了聊這個問題,就像最簡單的字符串,Redis並未沿襲傳統c語言的慣例,而是單獨構建了一種簡單的動態字符串抽象類型,並充分利用SDS實現。

當然,如果你想進一步瞭解Redis系統的設計理念,比如它通過什麼機制將數據緩存到內存中,開發大系統必備技術之Redis技術學習與研究或許會給你一些啓發,作者談到了Redis的歷史、流行度、設計思想,並通過支持Redis的Java客戶端Jedis ,用詳盡的代碼案例一步步演示了它支持的數據類型使用方法,它的事務特性、集羣等等,更爲具象地瞭解Redis的特點。

當我們對Redis的基本原理了然於胸後,再針對業務場景進行優化時,也能更合理地使用各種Redis命令。
 

Redis性能:禍福相依的內部運行機制

Redis的最大特點是使用內存來存儲數據,當內存超過物理內存的限制後,內存數據會和磁盤產生頻繁的交換,最終導致Redis性能急劇下降。所以在生產環境中我們通過配置參數maxmemoey來限制使用的內存大小。 在有趣的Redis:緩存被我寫滿了,該怎麼辦? 中,作者詳細解釋了2個常見的緩存淘汰算法LRU算法和LFU算法,如何刪除那些沒用的數據。

另一方面,Redis爲了把內存中的數據持久到磁盤上,也提供了完善的持久化機制,主要包括2種:

  • RDB:產生一個數據快照文件
  • AOF:實時追加命令的日誌文件

但是如果配置不合理,持久化會佔用過多內存從而影響性能。舉個例子,如果AOF的刷盤時機設置爲每次寫入都刷盤,由於每次寫命令都需要寫入文件並刷到磁盤中才會返回,當寫入量很大時,會增加磁盤IO的負擔,大大降低Redis的寫入性能。Redis 持久化是如何做的?一文聊聊 RDB和AOF對比分析 談到了這兩種持久化機制對Redis性能的影響,建議大家針對不同的業務場景選擇合適的持久化方式。

在討論Redis性能問題的時候,不得不提的一點是它的單線程結構,這裏的單線程指的是執行命令 ,比如一條命令從客戶端到達服務端不會立刻被執行,而是會進入一個隊列中等待,每次只會有一條指令被選中執行。【Redis破障之路】:Redis單線程架構 詳細分析了單線程模型的Redis爲什麼性能如此之高,能達到每秒萬級別的處理能力,簡單透露兩點:純內存訪問、I/O多路複用技術,具體可以閱讀文章。而Redis的單線程架構,也意味着網絡問題會對它的性能產生一定的影響。

另外,當業務規模擴大,單個Redis服務無法承載的時候,我們常常會用分佈式架構來提高Redis的性能,Redis主從複製以及哨兵的原理解讀 和 Redis Sentinel 源碼:Redis的高可用模型分析 都討論了主從模式下的關鍵功能:哨兵,通過對其源碼的理解,詳細說明了哨兵的代碼實現方式,並學會使用哨兵功能解決主節點的寫能力、存儲能力限制等等。

除此之外,諸如數據結構的複雜度、網絡帶寬、操作系統以及硬件本身都會對Redis的性能產生影響,它的性能問題幾乎涵蓋了 CPU、內存、網絡、磁盤的方方面面,再此不一一贅述。

綜上,我們分析了影響Redis性能的一些關鍵內部機制,比如它的緩存淘汰算法;它的持久化會佔用過多內存從而影響性能;它的單線程架構等。通過了解Redis的這些內部實現原理,也能進一步幫助大家排查它的性能問題。
 

Redis調優:宕機怎麼辦?收下這幾顆靈丹妙藥

下面,我們將給出一些應對Redis性能問題的解決方案。

以常見的緩存問題爲例,通常情況下,Redis緩存層由於某種原因宕機後,所有的請求會湧向存儲層,短時間內的高併發請求可能會導致存儲層掛機,稱之爲“Redis雪崩”。Redis緩存異常應對方案分析 有針對性的總結了Redis發生緩存穿透、雪崩、擊穿情況時,能夠有效應對的解決方案,比如不要給訪問頻繁的熱點數據設置過期時間,從而解決Redis實例沒有起到緩存層作用的問題。

大key也是影響Redis性能的關鍵因素,如果一個 key 寫入的 value 非常大,那麼 Redis 在分配內存時就會比較耗時。同樣的,當刪除這個 key 時,釋放內存也會比較耗時,這種類型的 key 我們一般稱之爲 大key。 在 分佈式緩存數據庫Redis大KEY問題定位及優化建議 中,作者就針對數據庫報錯OOM來一步步分析大key的問題,先是查看Redis集羣內存監控指標,確認內存異常分片,然後通過在線&離線工具分析,結果顯示大key導致數據大小分佈不均。對此作者給出了兩個方案:短期是刪除查詢到的key,長期是對大key進行拆分。

另一個經常被詬病性能問題的是fork, fork是開源Redis的一個重要依賴,當 Redis 開啓了後臺 RDB 和 AOF rewrite 後,在執行時,它們都需要主進程創建出一個子進程進行數據的持久化,fork就是創建子進程的系統調用函數。

在華爲雲GaussDB(for Redis)服務團隊支撐某客戶業務上雲的過程中 ,就發現了由fork引發的時延抖動問題,文章一場由fork引發的超時,讓我們重新探討了Redis的抖動問題 還原了當時的場景,探究了fork對性能的影響,包括業務抖動、內存率利用率降低和實例容量受限。比如,在電商大促、熱點事件等業務高峯時發生上述fork,會導致Redis阻塞,進而對業務造成雪崩的影響。

團隊通過修改日誌、系統性排查整改代碼中的 fork調用,最後在新版本GaussDB(for Redis)中解決了該問題,並清零了內部的fork使用,與原生Redis相比,徹底解決了fork的性能隱患。

其實,考慮到業務場景越來越複雜,原生Redis出現性能瓶頸難以避免。這時候,最簡單粗暴的解決方法就是使用商業版本的Redis,一勞永逸解決可能存在的性能問題。

在 GaussDB(for Redis)與原生Redis集羣的性能對比 中,就比較了華爲雲自研Redis和原生Redis集羣在X86架構下的性能測試報告,結果表明GaussDB(for Redis)在性能、抗寫和存儲成本上的優勢明顯。

從相識到相惜:Redis與計算存儲分離四部曲 進一步從技術角度拆解分析了GaussDB(for Redis)如何在存算分離的架構下,實現強一致、秒擴容、超可用、低成本。以強一致爲例,Redis遇到流量壓力進行主從切換時很容易發生數據不同步問題,GaussDB ( for Redis)就在存儲層(DFV層)去進行強一致的數據同步,而非計算層,這樣就避免了任何中間態下的數據的不一致,再也不用擔心宕機導致數據丟失。更多的技術細節揭祕,也可以閱讀這組專題高斯Redis揭祕系列文章,更全面的認識GaussDB ( for Redis)。

Redis的性能問題,涉及到的技術細節很多,本專題只是列出了一些較爲典型的問題,希望讀者能夠通過上述提及的技術文章,對它有更深入的認識,學會從底層運行機制去思考Redis的性能調優。

 

點擊關注,第一時間瞭解華爲雲新鮮技術~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章