阿里妹導讀 本文先講述了Redis變慢的判別方法,,后面講述了如何提升性能,。 一、Redis為什么變慢了 1.Redis真的變慢了嗎,?
從輸出結(jié)果可以看到,這 60 秒內(nèi)的最大響應延遲為 119 微秒(0.119毫秒),。你還可以使用以下命令,,查看一段時間內(nèi) Redis 的最小、最大,、平均訪問延遲 $ redis-cli -h 127.0.0.1 -p 6379 --latency-history -i 1 min: 0, max: 1, avg: 0.13 (100 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.12 (99 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.13 (99 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.10 (99 samples) -- 1.01 seconds range min: 0, max: 1, avg: 0.13 (98 samples) -- 1.00 seconds range min: 0, max: 1, avg: 0.08 (99 samples) -- 1.01 seconds range 如果你觀察到的 Redis 運行時延遲是其基線性能的 2 倍及以上,,就可以認定 Redis 變慢了。?
# 命令執(zhí)行耗時超過 5 毫秒,,記錄慢日志 CONFIG SET slowlog-log-slower-than 5000 # 只保留最近 500 條慢日志 CONFIG SET slowlog-max-len 500 3.操作bigkey
這里我需要提醒你的是,,當執(zhí)行這個命令時,要注意 2 個問題: 4.集中過期 5.實例內(nèi)存達到上限
一般最常使用的是 allkeys-lru / volatile-lru 淘汰策略,它們的處理邏輯是,,每次從實例中隨機取出一批 key(這個數(shù)量可配置),,然后淘汰一個最少訪問的 key,之后把剩下的 key 暫存到一個池子中,,繼續(xù)隨機取一批 key,,并與之前池子中的 key 比較,再淘汰一個最少訪問的 key,。以此往復,,直到實例內(nèi)存降到 maxmemory 之下。
如果此時你的 Redis 實例中還存儲了 bigkey,,那么在淘汰刪除 bigkey 釋放內(nèi)存時,也會耗時比較久,。 6.fork耗時嚴重 當 Redis 開啟了后臺 RDB 和 AOF rewrite 后,,在執(zhí)行時,,它們都需要主進程創(chuàng)建出一個子進程進行數(shù)據(jù)的持久化。 主進程創(chuàng)建子進程,,會調(diào)用操作系統(tǒng)提供的 fork 函數(shù),。 而 fork 在執(zhí)行過程中,主進程需要拷貝自己的內(nèi)存頁表給子進程,,如果這個實例很大,,那么這個拷貝的過程也會比較耗時。 而且這個 fork 過程會消耗大量的 CPU 資源,,在完成 fork 之前,,整個 Redis 實例會被阻塞住,無法處理任何客戶端請求,。 如果此時你的 CPU 資源本來就很緊張,,那么 fork 的耗時會更長,甚至達到秒級,,這會嚴重影響 Redis 的性能,。 那如何確認確實是因為 fork 耗時導致的 Redis 延遲變大呢? 你可以在 Redis 上執(zhí)行 INFO 命令,,查看 latest_fork_usec 項,,單位微秒。 # 上一次 fork 耗時,,單位微秒 latest_fork_usec:59477 這個時間就是主進程在 fork 子進程期間,,整個實例阻塞無法處理客戶端請求的時間。 如果你發(fā)現(xiàn)這個耗時很久,,就要警惕起來了,,這意味在這期間,你的整個 Redis 實例都處于不可用的狀態(tài),。 除了數(shù)據(jù)持久化會生成 RDB 之外,,當主從節(jié)點第一次建立數(shù)據(jù)同步時,主節(jié)點也創(chuàng)建子進程生成 RDB,,然后發(fā)給從節(jié)點進行一次全量同步,,所以,這個過程也會對 Redis 產(chǎn)生性能影響,。 7.開啟內(nèi)存大頁 除了上面講到的子進程 RDB 和 AOF rewrite 期間,fork 耗時導致的延時變大之外,,這里還有一個方面也會導致性能問題,,這就是操作系統(tǒng)是否開啟了內(nèi)存大頁機制。 什么是內(nèi)存大頁,? 我們都知道,,應用程序向操作系統(tǒng)申請內(nèi)存時,,是按內(nèi)存頁進行申請的,而常規(guī)的內(nèi)存頁大小是 4KB,。 Linux 內(nèi)核從 2.6.38 開始,,支持了內(nèi)存大頁機制,該機制允許應用程序以 2MB 大小為單位,,向操作系統(tǒng)申請內(nèi)存,。 應用程序每次向操作系統(tǒng)申請的內(nèi)存單位變大了,但這也意味著申請內(nèi)存的耗時變長,。 這對 Redis 會有什么影響呢,? 當 Redis 在執(zhí)行后臺 RDB,采用 fork 子進程的方式來處理,。但主進程 fork 子進程后,,此時的主進程依舊是可以接收寫請求的,而進來的寫請求,,會采用 Copy On Write(寫時復制)的方式操作內(nèi)存數(shù)據(jù),。 也就是說,主進程一旦有數(shù)據(jù)需要修改,,Redis 并不會直接修改現(xiàn)有內(nèi)存中的數(shù)據(jù),,而是先將這塊內(nèi)存數(shù)據(jù)拷貝出來,再修改這塊新內(nèi)存的數(shù)據(jù),,這就是所謂的「寫時復制」,。 寫時復制你也可以理解成,誰需要發(fā)生寫操作,,誰就需要先拷貝,,再修改。 這樣做的好處是,,父進程有任何寫操作,,并不會影響子進程的數(shù)據(jù)持久化(子進程只持久化 fork 這一瞬間整個實例中的所有數(shù)據(jù)即可,不關心新的數(shù)據(jù)變更,,因為子進程只需要一份內(nèi)存快照,,然后持久化到磁盤上)。 但是請注意,,主進程在拷貝內(nèi)存數(shù)據(jù)時,,這個階段就涉及到新內(nèi)存的申請,如果此時操作系統(tǒng)開啟了內(nèi)存大頁,,那么在此期間,,客戶端即便只修改 10B 的數(shù)據(jù),Redis 在申請內(nèi)存時也會以 2MB 為單位向操作系統(tǒng)申請,,申請內(nèi)存的耗時變長,,進而導致每個寫請求的延遲增加,,影響到 Redis 性能。 同樣地,,如果這個寫請求操作的是一個 bigkey,,那主進程在拷貝這個 bigkey 內(nèi)存塊時,一次申請的內(nèi)存會更大,,時間也會更久,。可見,,bigkey 在這里又一次影響到了性能,。 8.開啟AOF 前面我們分析了 RDB 和 AOF rewrite 對 Redis 性能的影響,主要關注點在 fork 上,。 其實,,關于數(shù)據(jù)持久化方面,還有影響 Redis 性能的因素,,這次我們重點來看 AOF 數(shù)據(jù)持久化,。 如果你的 AOF 配置不合理,還是有可能會導致性能問題,。 當 Redis 開啟 AOF 后,,其工作原理如下: 1.Redis 執(zhí)行寫命令后,把這個命令寫入到 AOF 文件內(nèi)存中(write 系統(tǒng)調(diào)用) 2.Redis 根據(jù)配置的 AOF 刷盤策略,,把 AOF 內(nèi)存數(shù)據(jù)刷到磁盤上(fsync 系統(tǒng)調(diào)用) 為了保證 AOF 文件數(shù)據(jù)的安全性,,Redis 提供了 3 種刷盤機制: 1.appendfsync always:主線程每次執(zhí)行寫操作后立即刷盤,此方案會占用比較大的磁盤 IO 資源,,但數(shù)據(jù)安全性最高 2.appendfsync no:主線程每次寫操作只寫內(nèi)存就返回,,內(nèi)存數(shù)據(jù)什么時候刷到磁盤,交由操作系統(tǒng)決定,,此方案對性能影響最小,,但數(shù)據(jù)安全性也最低,Redis 宕機時丟失的數(shù)據(jù)取決于操作系統(tǒng)刷盤時機 3.appendfsync everysec:主線程每次寫操作只寫內(nèi)存就返回,,然后由后臺線程每隔 1 秒執(zhí)行一次刷盤操作(觸發(fā)fsync系統(tǒng)調(diào)用),,此方案對性能影響相對較小,但當 Redis 宕機時會丟失 1 秒的數(shù)據(jù) 看到這里,,我猜你肯定和大多數(shù)人的想法一樣,,選比較折中的方案 appendfsync everysec 就沒問題了吧? 這個方案優(yōu)勢在于,,Redis 主線程寫完內(nèi)存后就返回,,具體的刷盤操作是放到后臺線程中執(zhí)行的,后臺線程每隔 1 秒把內(nèi)存中的數(shù)據(jù)刷到磁盤中,。 這種方案既兼顧了性能,,又盡可能地保證了數(shù)據(jù)安全,是不是覺得很完美,? 但是,,這里我要給你潑一盆冷水了,采用這種方案你也要警惕一下,,因為這種方案還是存在導致 Redis 延遲變大的情況發(fā)生,,甚至會阻塞整個 Redis。 你試想這樣一種情況:當 Redis 后臺線程在執(zhí)行 AOF 文件刷盤時,,如果此時磁盤的 IO 負載很高,,那這個后臺線程在執(zhí)行刷盤操作(fsync系統(tǒng)調(diào)用)時就會被阻塞住。 此時的主線程依舊會接收寫請求,,緊接著,,主線程又需要把數(shù)據(jù)寫到文件內(nèi)存中(write 系統(tǒng)調(diào)用),當主線程使用后臺子線程執(zhí)行了一次 fsync,,需要再次把新接收的操作記錄寫回磁盤時,,如果主線程發(fā)現(xiàn)上一次的 fsync 還沒有執(zhí)行完,那么它就會阻塞,。所以,,如果后臺子線程執(zhí)行的 fsync 頻繁阻塞的話(比如 AOF 重寫占用了大量的磁盤 IO 帶寬),主線程也會阻塞,,導致 Redis 性能變慢,。 看到了么?在這個過程中,,主線程依舊有阻塞的風險,。 所以,盡管你的 AOF 配置為 appendfsync everysec,,也不能掉以輕心,,要警惕磁盤壓力過大導致的 Redis 有性能問題。 那什么情況下會導致磁盤 IO 負載過大,?以及如何解決這個問題呢,? 我總結(jié)了以下幾種情況,你可以參考進行問題排查: 1.子進程正在執(zhí)行 AOF rewrite,,這個過程會占用大量的磁盤 IO 資源 2.有其他應用程序在執(zhí)行大量的寫文件操作,,也會占用磁盤 IO 資源 對于情況1,說白了就是,,Redis 的 AOF 后臺子線程刷盤操作,,撞上了子進程 AOF rewrite! 9.綁定CPU 很多時候,我們在部署服務時,,為了提高服務性能,,降低應用程序在多個 CPU 核心之間的上下文切換帶來的性能損耗,通常采用的方案是進程綁定 CPU 的方式提高性能,。 我們都知道,,一般現(xiàn)代的服務器會有多個 CPU,而每個 CPU 又包含多個物理核心,,每個物理核心又分為多個邏輯核心,,每個物理核下的邏輯核共用 L1/L2 Cache。 而 Redis Server 除了主線程服務客戶端請求之外,,還會創(chuàng)建子進程,、子線程。 其中子進程用于數(shù)據(jù)持久化,,而子線程用于執(zhí)行一些比較耗時操作,,例如異步釋放 fd、異步 AOF 刷盤,、異步 lazy-free 等等,。 如果你把 Redis 進程只綁定了一個 CPU 邏輯核心上,那么當 Redis 在進行數(shù)據(jù)持久化時,,fork 出的子進程會繼承父進程的 CPU 使用偏好,。 而此時的子進程會消耗大量的 CPU 資源進行數(shù)據(jù)持久化(把實例數(shù)據(jù)全部掃描出來需要耗費CPU),這就會導致子進程會與主進程發(fā)生 CPU 爭搶,,進而影響到主進程服務客戶端請求,,訪問延遲變大。 這就是 Redis 綁定 CPU 帶來的性能問題,。 10.使用Swap 如果你發(fā)現(xiàn) Redis 突然變得非常慢,,每次的操作耗時都達到了幾百毫秒甚至秒級,那此時你就需要檢查 Redis 是否使用到了 Swap,,在這種情況下 Redis 基本上已經(jīng)無法提供高性能的服務了,。 什么是 Swap?為什么使用 Swap 會導致 Redis 的性能下降,? 如果你對操作系統(tǒng)有些了解,,就會知道操作系統(tǒng)為了緩解內(nèi)存不足對應用程序的影響,允許把一部分內(nèi)存中的數(shù)據(jù)換到磁盤上,,以達到應用程序?qū)?nèi)存使用的緩沖,,這些內(nèi)存數(shù)據(jù)被換到磁盤上的區(qū)域,就是 Swap,。 問題就在于,,當內(nèi)存中的數(shù)據(jù)被換到磁盤上后,Redis 再訪問這些數(shù)據(jù)時,就需要從磁盤上讀取,,訪問磁盤的速度要比訪問內(nèi)存慢幾百倍,! 尤其是針對 Redis 這種對性能要求極高、性能極其敏感的數(shù)據(jù)庫來說,,這個操作延時是無法接受的,。 此時,,你需要檢查 Redis 機器的內(nèi)存使用情況,,確認是否存在使用了 Swap。 你可以通過以下方式來查看 Redis 進程是否使用到了 Swap:
如果只是少量數(shù)據(jù)被換到磁盤上,例如每一塊 Swap 占對應 Size 的比例很小,,那影響并不是很大,。如果是幾百兆甚至上 GB 的內(nèi)存被換到了磁盤上,那么你就需要警惕了,,這種情況 Redis 的性能肯定會急劇下降,。 11.碎片整理 Redis 的數(shù)據(jù)都存儲在內(nèi)存中,當我們的應用程序頻繁修改 Redis 中的數(shù)據(jù)時,,就有可能會導致 Redis 產(chǎn)生內(nèi)存碎片,。 內(nèi)存碎片會降低 Redis 的內(nèi)存使用率,我們可以通過執(zhí)行 INFO 命令,,得到這個實例的內(nèi)存碎片率: # Memory used_memory:5709194824 used_memory_human:5.32G used_memory_rss:8264855552 used_memory_rss_human:7.70G ... mem_fragmentation_ratio:1.45 很簡單,mem_fragmentation_ratio = used_memory_rss / used_memory,。 其中 used_memory 表示 Redis 存儲數(shù)據(jù)的內(nèi)存大小,,而 used_memory_rss 表示操作系統(tǒng)實際分配給 Redis 進程的大小。 如果 mem_fragmentation_ratio > 1.5,,說明內(nèi)存碎片率已經(jīng)超過了 50%,,這時我們就需要采取一些措施來降低內(nèi)存碎片了。 解決的方案一般如下: 1.如果你使用的是 Redis 4.0 以下版本,,只能通過重啟實例來解決 2.如果你使用的是 Redis 4.0 版本,,它正好提供了自動碎片整理的功能,可以通過配置開啟碎片自動整理,。 但是,,開啟內(nèi)存碎片整理,它也有可能會導致 Redis 性能下降。 原因在于,,Redis 的碎片整理工作是也在主線程中執(zhí)行的,,當其進行碎片整理時,必然會消耗 CPU 資源,,產(chǎn)生更多的耗時,,從而影響到客戶端的請求。 所以,,當你需要開啟這個功能時,,最好提前測試評估它對 Redis 的影響。 Redis 碎片整理的參數(shù)配置如下: # 開啟自動內(nèi)存碎片整理(總開關) activedefrag yes
# 內(nèi)存使用 100MB 以下,,不進行碎片整理 active-defrag-ignore-bytes 100mb
# 內(nèi)存碎片率超過 10%,,開始碎片整理 active-defrag-threshold-lower 10 # 內(nèi)存碎片率超過 100%,盡最大努力碎片整理 active-defrag-threshold-upper 100
# 內(nèi)存碎片整理占用 CPU 資源最小百分比 active-defrag-cycle-min 1 # 內(nèi)存碎片整理占用 CPU 資源最大百分比 active-defrag-cycle-max 25
# 碎片整理期間,,對于 List/Set/Hash/ZSet 類型元素一次 Scan 的數(shù)量 active-defrag-max-scan-fields 1000 二,、Redis如何優(yōu)化 1.慢查詢優(yōu)化 1.盡量不使用 O(N) 以上復雜度過高的命令,對于數(shù)據(jù)的聚合操作,,放在客戶端做 2.執(zhí)行 O(N) 命令,,保證 N 盡量的小(推薦 N <= 300),,每次獲取盡量少的數(shù)據(jù),,讓 Redis 可以及時處理返回 2.集中過期優(yōu)化 一般有兩種方案來規(guī)避這個問題: 1.集中過期 key 增加一個隨機過期時間,把集中過期的時間打散,,降低 Redis 清理過期 key 的壓力 2.如果你使用的 Redis 是 4.0 以上版本,,可以開啟 lazy-free 機制,當刪除過期 key 時,,把釋放內(nèi)存的操作放到后臺線程中執(zhí)行,,避免阻塞主線程。 第一種方案,,在設置 key 的過期時間時,,增加一個隨機時間,偽代碼可以這么寫: # 在過期時間點之后的 5 分鐘內(nèi)隨機過期掉 redis.expireat(key, expire_time + random(300))
在這里我們需要重點關注 expired_keys 這一項,,它代表整個實例到目前為止,,累計刪除過期 key 的數(shù)量,。 你需要把這個指標監(jiān)控起來,當這個指標在很短時間內(nèi)出現(xiàn)了突增,,需要及時報警出來,,然后與業(yè)務應用報慢的時間點進行對比分析,確認時間是否一致,,如果一致,,則可以確認確實是因為集中過期 key 導致的延遲變大。 3.實例內(nèi)存達到上限優(yōu)化 1.避免存儲 bigkey,,降低釋放內(nèi)存的耗時 2.淘汰策略改為隨機淘汰,,隨機淘汰比 LRU 要快很多(視業(yè)務情況調(diào)整) 3.拆分實例,把淘汰 key 的壓力分攤到多個實例上 4.如果使用的是 Redis 4.0 以上版本,,開啟 layz-free 機制,,把淘汰 key 釋放內(nèi)存的操作放到后臺線程中執(zhí)行(配置 lazyfree-lazy-eviction = yes) 4.fork耗時嚴重優(yōu)化 1.控制 Redis 實例的內(nèi)存:盡量在 10G 以下,執(zhí)行 fork 的耗時與實例大小有關,,實例越大,耗時越久,。 2.合理配置數(shù)據(jù)持久化策略:在 slave 節(jié)點執(zhí)行 RDB 備份,,推薦在低峰期執(zhí)行,而對于丟失數(shù)據(jù)不敏感的業(yè)務(例如把 Redis 當做純緩存使用),,可以關閉 AOF 和 AOF rewrite,。 3.Redis 實例不要部署在虛擬機上:fork 的耗時也與系統(tǒng)也有關,虛擬機比物理機耗時更久,。 4.降低主從庫全量同步的概率:適當調(diào)大 repl-backlog-size 參數(shù),,避免主從全量同步。
5.多核CPU優(yōu)化 那如何解決這個問題呢,? 如果你確實想要綁定 CPU,可以優(yōu)化的方案是,,不要讓 Redis 進程只綁定在一個 CPU 邏輯核上,,而是綁定在多個邏輯核心上,而且,,綁定的多個邏輯核心最好是同一個物理核心,,這樣它們還可以共用 L1/L2 Cache。 當然,,即便我們把 Redis 綁定在多個邏輯核心上,,也只能在一定程度上緩解主線程、子進程,、后臺線程在 CPU 資源上的競爭,。 因為這些子進程、子線程還是會在這多個邏輯核心上進行切換,,存在性能損耗,。? 如何再進一步優(yōu)化? 可能你已經(jīng)想到了,,我們是否可以讓主線程,、子進程、后臺線程,,分別綁定在固定的 CPU 核心上,,不讓它們來回切換,這樣一來,,他們各自使用的 CPU 資源互不影響,。 其實,這個方案 Redis 官方已經(jīng)想到了,。 Redis 在 6.0 版本已經(jīng)推出了這個功能,,我們可以通過以下配置,對主線程,、后臺線程,、后臺 RDB 進程、AOF rewrite 進程,,綁定固定的 CPU 邏輯核心: Redis6.0 前綁定CPU核
# Redis Server 和 IO 線程綁定到 CPU核心 0,2,4,6 server_cpulist 0-7:2 # 后臺子線程綁定到 CPU核心 1,3 bio_cpulist 1,3 # 后臺 AOF rewrite 進程綁定到 CPU 核心 8,9,10,11 aof_rewrite_cpulist 8-11 # 后臺 RDB 進程綁定到 CPU 核心 1,10,11 # bgsave_cpulist 1,10-1 這里我需要提醒你的是,,一般來說,,Redis 的性能已經(jīng)足夠優(yōu)秀,除非你對 Redis 的性能有更加嚴苛的要求,,否則不建議你綁定 CPU,。 6.查看Redis內(nèi)存是否發(fā)生Swap
$cat smaps | egrep '^(Swap|Size)' Size: 584 kB Swap: 0 kB Size: 4 kB Swap: 4 kB Size: 4 kB Swap: 0 kB Size: 462044 kB Swap: 462008 kB Size: 21392 kB Swap: 0 kB 7.內(nèi)存大頁 如果采用了內(nèi)存大頁,,那么,即使客戶端請求只修改 100B 的數(shù)據(jù),,Redis 也需要拷貝 2MB 的大頁。相反,,如果是常規(guī)內(nèi)存頁機制,,只用拷貝 4KB。兩者相比,,你可以看到,,當客戶端請求修改或新寫入數(shù)據(jù)較多時,內(nèi)存大頁機制將導致大量的拷貝,,這就會影響 Redis 正常的訪存操作,,最終導致性能變慢。 首先,,我們要先排查下內(nèi)存大頁,。方法是:在 Redis 實例運行的機器上執(zhí)行如下命令:
在實際生產(chǎn)環(huán)境中部署時,,我建議你不要使用內(nèi)存大頁機制,,操作也很簡單,只需要執(zhí)行下面的命令就可以了:
但是對于 Redis 這種對性能和延遲極其敏感的數(shù)據(jù)庫來說,,我們希望 Redis 在每次申請內(nèi)存時,耗時盡量短,,所以我不建議你在 Redis 機器上開啟這個機制,。 8.刪除使用Lazy Free 支持版本:Redis 4.0+ 8.1 主動刪除鍵使用lazy freeUNLINK命令127.0.0.1:7000> LLEN mylist (integer) 2000000 127.0.0.1:7000> UNLINK mylist (integer) 1 127.0.0.1:7000> SLOWLOG get 1) 1) (integer) 1 2) (integer) 1505465188 3) (integer) 30 4) 1) 'UNLINK' 2) 'mylist' 5) '127.0.0.1:17015' 6) '' FLUSHALL/FLUSHDB ASYNC
8.2 被動刪除鍵使用lazy freelazy free應用于被動刪除中,目前有4種場景,,每種場景對應一個配置參數(shù),;默認都是關閉。 lazyfree-lazy-eviction no lazyfree-lazy-expire no lazyfree-lazy-server-del no slave-lazy-flush no lazyfree-lazy-eviction針對redis內(nèi)存使用達到maxmeory,,并設置有淘汰策略時,;在被動淘汰鍵時,是否采用lazy free機制,;因為此場景開啟lazy free, 可能使用淘汰鍵的內(nèi)存釋放不及時,,導致redis內(nèi)存超用,超過maxmemory的限制,。此場景使用時,,請結(jié)合業(yè)務測試。(生產(chǎn)環(huán)境不建議設置yes) lazyfree-lazy-expire 針對設置有TTL的鍵,,達到過期后,,被redis清理刪除時是否采用lazy free機制;此場景建議開啟,,因TTL本身是自適應調(diào)整的速度,。 lazyfree-lazy-server-del針對有些指令在處理已存在的鍵時,會帶有一個隱式的DEL鍵的操作,。如rename命令,,當目標鍵已存在,redis會先刪除目標鍵,如果這些目標鍵是一個big key,那就會引入阻塞刪除的性能問題,。此參數(shù)設置就是解決這類問題,,建議可開啟。 slave-lazy-flush針對slave進行全量數(shù)據(jù)同步,,slave在加載master的RDB文件前,,會運行flushall來清理自己的數(shù)據(jù)場景,, 參數(shù)設置決定是否采用異常flush機制。如果內(nèi)存變動不大,,建議可開啟,。可減少全量同步耗時,,從而減少主庫因輸出緩沖區(qū)爆漲引起的內(nèi)存使用增長,。 8.3 lazy free的監(jiān)控lazy free能監(jiān)控的數(shù)據(jù)指標,只有一個值:lazyfree_pending_objects,,表示redis執(zhí)行l(wèi)azy free操作,,在等待被實際回收內(nèi)容的鍵個數(shù)。并不能體現(xiàn)單個大鍵的元素個數(shù)或等待lazy free回收的內(nèi)存大小,。所以此值有一定參考值,,可監(jiān)測redis lazy free的效率或堆積鍵數(shù)量;比如在flushall async場景下會有少量的堆積,。
9.AOF優(yōu)化 Redis 提供了一個配置項,當子進程在 AOF rewrite 期間,,可以讓后臺子線程不執(zhí)行刷盤(不觸發(fā) fsync 系統(tǒng)調(diào)用)操作。 這相當于在 AOF rewrite 期間,,臨時把 appendfsync 設置為了 none,,配置如下: # AOF rewrite 期間,AOF 后臺子線程不進行刷盤操作 # 相當于在這期間,,臨時把 appendfsync 設置為了 none no-appendfsync-on-rewrite yes 如果占用磁盤資源的是其他應用程序,,那就比較簡單了,你需要定位到是哪個應用程序在大量寫磁盤,,然后把這個應用程序遷移到其他機器上執(zhí)行就好了,,避免對 Redis 產(chǎn)生影響。 當然,,如果你對 Redis 的性能和數(shù)據(jù)安全都有很高的要求,,那么建議從硬件層面來優(yōu)化,更換為 SSD 磁盤,,提高磁盤的 IO 能力,,保證 AOF 期間有充足的磁盤資源可以使用。同時盡可能讓Redis運行在獨立的機器上,。 10.Swap優(yōu)化 1.增加機器的內(nèi)存,,讓 Redis 有足夠的內(nèi)存可以使用 2.整理內(nèi)存空間,釋放出足夠的內(nèi)存供 Redis 使用,,然后釋放 Redis 的 Swap,,讓 Redis 重新使用內(nèi)存 釋放 Redis 的 Swap 過程通常要重啟實例,為了避免重啟實例對業(yè)務的影響,,一般會先進行主從切換,,然后釋放舊主節(jié)點的 Swap,重啟舊主節(jié)點實例,,待從庫數(shù)據(jù)同步完成后,,再進行主從切換即可。 預防的辦法就是,,你需要對 Redis 機器的內(nèi)存和 Swap 使用情況進行監(jiān)控,,在內(nèi)存不足或使用到 Swap 時報警出來,及時處理,。 三,、Redis變慢了排查步驟 1、獲取 Redis 實例在當前環(huán)境下的基線性能,。 2,、是否用了慢查詢命令?如果是的話,,就使用其他命令替代慢查詢命令,,或者把聚合計算命令放在客戶端做。 3,、是否對過期 key 設置了相同的過期時間,?對于批量刪除的 key,可以在每個 key 的過期時間上加一個隨機數(shù),避免同時刪除,。 4,、是否存在 bigkey?對于 bigkey 的刪除操作,,如果你的 Redis 是 4.0 及以上的版本,,可以直接利用異步線程機制減少主線程阻塞;如果是 Redis 4.0 以前的版本,,可以使用 SCAN 命令迭代刪除,;對于 bigkey 的集合查詢和聚合操作,可以使用 SCAN 命令在客戶端完成,。 5,、Redis AOF 配置級別是什么?業(yè)務層面是否的確需要這一可靠性級別,?如果我們需要高性能,,同時也允許數(shù)據(jù)丟失,可以將配置項 no-appendfsync-on-rewrite 設置為 yes,,避免 AOF 重寫和 fsync 競爭磁盤 IO 資源,,導致 Redis 延遲增加。當然,, 如果既需要高性能又需要高可靠性,,最好使用高速固態(tài)盤作為 AOF 日志的寫入盤。 6,、Redis 實例的內(nèi)存使用是否過大,?發(fā)生 swap 了嗎?如果是的話,,就增加機器內(nèi)存,,或者是使用 Redis 集群,分攤單機 Redis 的鍵值對數(shù)量和內(nèi)存壓力,。同時,,要避免出現(xiàn) Redis 和其他內(nèi)存需求大的應用共享機器的情況。 7,、在 Redis 實例的運行環(huán)境中,,是否啟用了透明大頁機制?如果是的話,,直接關閉內(nèi)存大頁機制就行了。 8,、是否運行了 Redis 主從集群,?如果是的話,把主庫實例的數(shù)據(jù)量大小控制在 2~4GB,以免主從復制時,,從庫因加載大的 RDB 文件而阻塞,。 9、是否使用了多核 CPU 或 NUMA 架構(gòu)的機器運行 Redis 實例,?使用多核 CPU 時,,可以給 Redis 實例綁定物理核;使用 NUMA 架構(gòu)時,,注意把 Redis 實例和網(wǎng)絡中斷處理程序運行在同一個 CPU Socket 上,。 “飛天免費試用計劃”來啦!免費領用 阿里云推出“飛天免費試用計劃”,,面向國內(nèi)1000萬云上開發(fā)者,,提供包括ECS、數(shù)據(jù)庫PolarDB,、機器學習PAI等在內(nèi) 60 多款云產(chǎn)品的免費試用,,時長支持1個月、3個月到長期免費,。 |
|
來自: 昵稱10087950 > 《中間件》