日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

你还不知道Redis 高延迟时发生了啥嘛?

發(fā)布時間:2025/3/16 数据库 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 你还不知道Redis 高延迟时发生了啥嘛? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Redis 是一種內(nèi)存數(shù)據(jù)庫,將數(shù)據(jù)保存在內(nèi)存中,讀寫效率要比傳統(tǒng)的將數(shù)據(jù)保存在磁盤上的數(shù)據(jù)庫要快很多。但是 Redis 也會發(fā)生延遲時,這是就需要我們對其產(chǎn)生原因有深刻的了解,以便于快速排查問題,解決 Redis的延遲問題

一條命令執(zhí)行過程

在本文場景下,延遲 (latency) 是指從客戶端發(fā)送命令到客戶端接收到命令返回值的時間間隔。所以我們先來看一下 Redis 一條命令執(zhí)行的步驟,其中每個步驟出問題都可能導(dǎo)致高延遲。

上圖是 Redis 客戶端發(fā)送一條命令的執(zhí)行過程示意圖,綠色的是執(zhí)行步驟,而藍色的則是可能出現(xiàn)的導(dǎo)致高延遲的原因。

網(wǎng)絡(luò)連接限制、網(wǎng)絡(luò)傳輸速率和CPU性能等是所有服務(wù)端都可能產(chǎn)生的性能問題。但是 Redis 有自己獨有的可能導(dǎo)致高延遲的問題:命令或者數(shù)據(jù)結(jié)構(gòu)誤用、持久化阻塞和內(nèi)存交換。

而且更為致命的是,Redis 采用單線程和事件驅(qū)動的機制來處理網(wǎng)絡(luò)請求,分別有對應(yīng)的連接應(yīng)答處理器,命令請求處理器和命令回復(fù)處理器來處理客戶端的網(wǎng)絡(luò)請求事件,處理完一個事件就繼續(xù)處理隊列中的下一個。一條命令處理出現(xiàn)了高延遲會影響接下來處于排隊狀態(tài)的其他命令。有關(guān) Redis 事件處理機制的可以參考本篇文章。

對于高延遲,Redis 原生提供慢查詢統(tǒng)計功能,執(zhí)行 slowlog get {n} 命令可以獲取最近的 n 條慢查詢命令,默認(rèn)對于執(zhí)行超過10毫秒(可配置)的命令都會記錄到一個定長隊列中,線上實例建議設(shè)置為1毫秒便于及時發(fā)現(xiàn)毫秒級以上的命令。

  • # 超過 slowlog-log-slower-than 閾值的命令都會被記錄到慢查詢隊列中

  • # 隊列最大長度為 slowlog-max-len

  • slowlog-log-slower-than 10000

  • slowlog-max-len 128

  • 如果命令執(zhí)行時間在毫秒級,則實例實際OPS只有1000左右。慢查詢隊列長度默認(rèn)128,可適當(dāng)調(diào)大。慢查詢本身只記錄了命令執(zhí)行時間,不包括數(shù)據(jù)網(wǎng)絡(luò)傳輸時間和命令排隊時間,因此客戶端發(fā)生阻塞異常 后,可能不是當(dāng)前命令緩慢,而是在等待其他命令執(zhí)行。需要重點比對異常和慢查詢發(fā)生的時間點,確認(rèn)是否有慢查詢造成的命令阻塞排隊。

    slowlog的輸出格式如下所示。第一個字段表示該條記錄在所有慢日志中的序號,最新的記錄被展示在最前面;第二個字段是這條記錄被記錄時的系統(tǒng)時間,可以用 date 命令來將其轉(zhuǎn)換為友好的格式第三個字段表示這條命令的響應(yīng)時間,單位為 us (微秒);第四個字段為對應(yīng)的 Redis 操作。

  • > slowlog get

  • 1) 1) (integer) 26

  • 2) (integer) 1450253133

  • 3) (integer) 43097

  • 4) 1) "flushdb"

  • 下面我們就來依次看一下不合理地使用命令或者數(shù)據(jù)結(jié)構(gòu)、持久化阻塞和內(nèi)存交換所導(dǎo)致的高延遲問題。

    不合理的命令或者數(shù)據(jù)結(jié)構(gòu)

    一般來說 Redis 執(zhí)行命令速度都非常快,但是當(dāng)數(shù)據(jù)量達到一定級別時,某些命令的執(zhí)行就會花費大量時間,比如對一個包含上萬個元素的 hash 結(jié)構(gòu)執(zhí)行 hgetall 操作,由于數(shù)據(jù)量比較大且命令算法復(fù)雜度是 O(n),這條命令執(zhí)行速度必然很慢。

    這個問題就是典型的不合理使用命令和數(shù)據(jù)結(jié)構(gòu)。對于高并發(fā)的場景我們應(yīng)該盡量避免在大對象上執(zhí)行算法復(fù)雜度超過 O(n) 的命令。對于鍵值較多的 hash 結(jié)構(gòu)可以使用 scan 系列命令來逐步遍歷,而不是直接使用 hgetall 來全部獲取。

    Redis 本身提供發(fā)現(xiàn)大對象的工具,對應(yīng)命令:redis-cli-h {ip} -p {port} bigkeys。這條命令會使用 scan 從指定的 Redis DB 中持續(xù)采樣,實時輸出當(dāng)時得到的 value 占用空間最大的 key 值,并在最后給出各種數(shù)據(jù)結(jié)構(gòu)的 biggest key 的總結(jié)報告。

  • > redis-cli -h host -p 12345--bigkeys

  • # Scanning the entire keyspace to find biggest keys as well as

  • # average sizes per key type. You can use -i 0.1 to sleep 0.1 sec

  • # per 100 SCAN commands (not usually needed).

  • [00.00%] Biggest hash found so far 'idx:user'with1 fields

  • [00.00%] Biggest hash found so far 'idx:product'with3 fields

  • [00.00%] Biggest hash found so far 'idx:order'with14 fields

  • [02.29%] Biggest hash found so far 'idx:fund'with16 fields

  • [02.29%] Biggest hash found so far 'idx:pay'with69 fields

  • [04.45%] Biggestset found so far 'indexed_word_set'with1482 members

  • [05.93%] Biggest hash found so far 'idx:address'with159 fields

  • [11.79%] Biggest hash found so far 'idx:reply'with196 fields

  • -------- summary -------

  • Sampled1484 keys in the keyspace!

  • Total key length in bytes is13488(avg len 9.09)

  • Biggestset found 'indexed_word_set' has 1482 members

  • Biggest hash found 'idx:的' has 196 fields

  • 0 strings with0 bytes (00.00% of keys, avg size 0.00)

  • 0 lists with0 items (00.00% of keys, avg size 0.00)

  • 2 sets with1710 members (00.13% of keys, avg size 855.00)

  • 1482 hashs with6731 fields (99.87% of keys, avg size 4.54)

  • 0 zsets with0 members (00.00% of keys, avg size 0.00)

  • 持久化阻塞

    對于開啟了持久化功能的Redis節(jié)點,需要排查是否是持久化導(dǎo)致的阻 塞。持久化引起主線程阻塞的操作主要有:fork 阻塞、AOF刷盤阻塞。

    fork 操作發(fā)生在 RDB 和 AOF 重寫時,Redis 主線程調(diào)用 fork 操作產(chǎn)生共享內(nèi)存的子進程,由子進程完成對應(yīng)的持久化工作。如果 fork 操作本身耗時過長,必然會導(dǎo)致主線程的阻塞。

    Redis 執(zhí)行 fork 操作產(chǎn)生的子進程內(nèi)存占用量表現(xiàn)為與父進程相同,理論上需要一倍的物理內(nèi)存來完成相應(yīng)的操作。但是 Linux 具有寫時復(fù)制技術(shù) (copy-on-write),父子進程會共享相同的物理內(nèi)存頁,當(dāng)父進程處理寫請求時會對需要修改的頁復(fù)制出一份副本完成寫操作,而子進程依然讀取 fork 時整個父進程的內(nèi)存快照。所以,一般來說,fork 不會消耗過多時間。

    可以執(zhí)行 info stats命令獲取到 latestforkusec 指標(biāo),表示 Redis 最近一次 fork 操作耗時,如果耗時很大,比如超過1秒,則需要做出優(yōu)化調(diào)整。

  • > redis-cli -c -p 7000 info | grep -w latest_fork_usec

  • latest_fork_usec:315

  • 當(dāng)我們開啟AOF持久化功能時,文件刷盤的方式一般采用每秒一次,后 臺線程每秒對AOF文件做 fsync 操作。當(dāng)硬盤壓力過大時,fsync 操作需要等待,直到寫入完成。如果主線程發(fā)現(xiàn)距離上一次的 fsync 成功超過2秒,為了數(shù)據(jù)安全性它會阻塞直到后臺線程執(zhí)行 fsync 操作完成。這種阻塞行為主要是硬盤壓力引起,可以查看 Redis日志識別出這種情況,當(dāng)發(fā)生這種阻塞行為時,會打印如下日志:

  • Asynchronous AOF fsync is taking too long(disk is busy). \

  • Writing the AOF buffer without waiting for fsync to complete, \

  • this may slow down Redis.

  • 也可以查看 info persistence 統(tǒng)計中的 aofdelayedfsync 指標(biāo),每次發(fā)生 fdatasync 阻塞主線程時會累加。

  • >info persistence

  • loading:0

  • aof_pending_bio_fsync:0

  • aof_delayed_fsync:0

  • 內(nèi)存交換

    內(nèi)存交換(swap)對于 Redis 來說是非常致命的,Redis 保證高性能的一個重要前提是所有的數(shù)據(jù)在內(nèi)存中。如果操作系統(tǒng)把 Redis 使用的部分內(nèi)存換出到硬盤,由于內(nèi)存與硬盤讀寫速度差幾個數(shù)量級,會導(dǎo)致發(fā)生交換后的 Redis 性能急劇下降。識別 Redis 內(nèi)存交換的檢查方法如下:

  • >redis-cli -p 6383 info server | grep process_id # 查詢 redis 進程號

  • >cat /proc/4476/smaps | grep Swap# 查詢內(nèi)存交換大小

  • Swap: 0 kB

  • Swap: 4 kB

  • Swap: 0 kB

  • Swap: 0 kB

  • 如果交換量都是0KB或者個別的是4KB,則是正常現(xiàn)象,說明Redis進程內(nèi)存沒有被交換。

    有很多方法可以避免內(nèi)存交換的發(fā)生。比如說:

    • 保證機器充足的可用內(nèi)存

    • 確保所有Redis實例設(shè)置最大可用內(nèi)存(maxmemory),防止極端情況下 Redis 內(nèi)存不可控的增長。

    • 降低系統(tǒng)使用swap優(yōu)先級,如?echo10>/proc/sys/vm/swappiness。

    參考

    • https://redis.io/topics/latency

    有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

    歡迎大家關(guān)注Java之道公眾號

    好文章,我在看??

    新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!

    總結(jié)

    以上是生活随笔為你收集整理的你还不知道Redis 高延迟时发生了啥嘛?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。