redis.conf 7.0 配置和原理全解,生產王者必備

5.5 redis.conf 配置詳解

我是 Redis, 當程序員用指令 ./redis-server /path/to/redis.conf 把我啓動的時候,第一個參數必須是redis.conf 文件的路徑。

這個文件很重要,就好像是你們的 DNA,它能控制我的運行情況,不同的配置會有不同的特性和人生,它掌握我的人生命運,控制着我如何完成高可用、高性能。合理的配置能讓我更快、更省內存,併發揮我最大的優勢讓我更安全運行。

以下這些配置大家必知必會,需要大家掌握每個配置背後的技術原理,學會融合貫通並在生產中正確配置,解決問題。避免出現技術懸浮,原理說的叭叭叭,配置像個大傻瓜。

本文配置文件版本是 Redis 7.0。

5.5.1 常規通用配置

這些是我的常規配置,每個 Redis 啓動必備參數,你一定要掌握,涉及到網絡、模塊插件、運行模式、日誌等。

MODULES

這個配置可以加載模塊插件增強我的功能,常見的模塊有 RedisSearch、RedisBloom 等。關於模塊加載可以參考【5.6 布隆過濾器原理與實戰】章節集成布隆過濾器便是通過以下配置實現加載布隆過濾器插件。

loadmodule /opt/app/RedisBloom-2.2.14/redisbloom.so

NETWORK

這部分都是與網絡相關的配置,很重要滴,配置不當將會有安全和性能問題。

bind

bind用於綁定本機的網絡接口(網卡),注意是本機。

每臺機器可能有多個網卡,每個網卡都有一個 IP 地址。配置了 bind,則表示我只允許來自本機指定網卡的 Redis 請求。

MySQL:“bind 是用於限制訪問你的機器 IP 麼?”

非也,注意,這個配置指的並不是只有 bind 指定的 IP 地址的計算機才能訪問我。如果想限制指定的主機連接我,只能通過防火牆來控制,bind 參數不也能起到這個作用。

舉個例子:如果我所在的服務器有兩個網卡,每個網卡有一個 IP 地址, IP1,IP2。

配置 bind IP1,則表示只能通過這個網卡地址來的網絡請求訪問我,也可以使用空格分割綁定多個網卡 IP。

我的默認配置是bind 127.0.0.1 -::1 表示綁定本地迴環地址 IPv4 和 Ipv6。- 表示當 ip 不存在也能啓動成功。

protected-mode

MySQL:網絡世界很危險滴,你如何保證安全?

默認開啓保護模式,如果沒有設置密碼或者沒有 bind 配置,我只允許在本機連接我,其它機器無法連接

如果想讓其它機器連接我,有以下三種方式。

  1. 配置爲 protected-mode no(不建議,地球很危險滴,防人之心不可無)。
  2. protected-mode yes,配置 bind 綁定本機的 IP。
  3. protected-mode yes,除了設置 bind 以外,還可以通過 requirepass magebyte設置密碼爲 magebyte, 讓其他機器的客戶端能使用密碼訪問我。

bind、protected-mode、requirepass 之間的關係

  • bind:指定的是我所在服務器網卡的 IP,不是指定某個可以訪問我的機器。
  • protected-mode:保護模式,默認開啓,如果沒有設置密碼或者 bind IP,我只接受本機訪問(沒密碼+保護模式啓動=本地訪問)。
  • requirepass,Redis 客戶端連接我通行的密碼。

如果參數設置爲bind 127.0.0.1 -::1,不管 protected-mode是否開啓,只能本機用 127.0.0.1 連接,其他外機無法連接。

在生產環境中,爲了安全,不要關閉 protected-mode,並設置 requirepass 參數配置密碼和 bind 綁定機器的網卡 IP。

port 6379

用於指定我監聽的客戶端 socket 端口號,默認 6379。設置爲 0 則不會監聽 TCP 連接,我想沒人設置爲 0 吧。

tcp-backlog 511

用於在 Linux 系統中控制 TCP 三次握手已完成連接隊列(完成三次握手後)的長度,如果已完成連接隊列已經滿則無法放入,客戶端會報read timeout或者connection reset by peer的錯。

MySQL:“在高併發系統中這玩意需要調大些吧?”

是的,我的默認配置是 511,這個配置的值不能大於 Linux 系統定義的 /proc/sys/net/core/somaxconn 值,Linux 默認的是 128。

所以我在啓動的時候你會看到這樣的警告:WARNING: The TCP backlog setting of 511 cannot be enforced because kern.ipc.somaxconn is set to the lower value of 128.

當系統併發量大並且客戶端速度緩慢的時候,在高併發系統中,需要設置一個較高的值來避免客戶端連接速度慢的問題。

需要分別調整 Linux 和 Redis 的配置。

建議修改爲 2048 或者更大,Linux 則在 /etc/sysctl.conf中添加net.core.somaxconn = 2048配置,並且在終端執行 sysctl -p即可。

碼哥使用 macOS 系統,使用 sudo sysctl -w kern.ipc.somaxconn=2048即可。

timeout

timeout 60 單位是秒,如果在 timout 時間內客戶端跟我沒有數據交互(客戶端不再向我發送任何數據),我將關閉該客戶端連接。

注意事項

  • 0 表示永不斷開。
  • timeout 對應源碼 server.maxidletime

tcp-keepalive

tcp-keepalive 300 單位是秒,官方建議值是 300。這是一個很有用的配置,實現 TCP 連接複用。

用途

用於客戶端與服務端的長連接,如果設置爲非 0,則使用 SO_KEEPALIVE 週期性發送 ACK 給客戶端,俗話就是用來定時向客戶端發送 tcp_ack 包來探測客戶端是否存活,並保持該連接。不用每次請求都建立 TCP 連接,畢竟創建連接是比較慢的。

常規配置

這些都是我的常規配置,比較通用,你必須瞭解。你可以把這些配置寫到一個特有文件中,其他節點可以使用 include /path/to/other.conf 配置來加載並複用該配置文件的配置。

daemonize

配置daemonize yes表示使用守護進程的模式運行,默認情況下我是以非守護線程的模式運行(daemonize no),開啓守護進程模式,會生成一個 .pid文件存儲進程號。

你也可以配置 pidfile /var/run/redis_6379.pid 參數來指定文件的生成目錄,當關閉服務的時候我會自動刪除該文件。

loglevel

指定我在運行時的日誌記錄級別。默認是 loglevel notice。有以下幾個選項可以配置。

  • debug:會記錄很多信息,主要用於開發和測試。
  • verbose:許多用處不大的信息,但是比 debug 少,如果發現生產出現一些問題無從下手,可使用該級別來輔助定位。
  • notice:生產一般配置這個級別。
  • warning:只會記錄非常重要/關鍵的的日誌。

logfile

指定日誌文件目錄,默認是 logfile "",表示只在標準控制檯輸出。

需要注意的是,如果使用標準控制檯輸出,並且使用守護進程的模式運行,日誌會發送到 /dev/null。

databases

設置數據庫數量,我的默認配置是 databases 16 。默認的數據庫是 DB 0,使用集羣模式的時候, database 只有一個,就是 DB 0

5.5.2 RDB 快照持久化

MySQL:“要怎麼開啓 RDB 內存快照文件實現持久化呢?”

RDB 快照持久化相關的配置,必須掌握,合理配置能我實現宕機快速恢復實現高可用。

save

使用 save <seconds> <changes> 開啓持久化,比如 save 60 100 表示 60 秒內,至少執行了 100 個寫操作,則執行 RDB 內存快照保存。

不關心是否丟失數據,你也可以通過配置 save "" 來禁用 RDB 快照保存,讓我性能起飛,衝出三界外。

默認情況的我會按照如下規則來保存 RDB 內存快照。

  • 在 3600 秒 (一個小時) 內,至少執行了一次更改。
  • 在 300 秒(5 分鐘)內,至少執行了 100 個更改。
  • 在 60 秒後,至少執行了 10000 個更改。

也可以通過 save 3600 1 300 100 60 10000 配置來顯示設置。

stop-writes-on-bgsave-error

MySQL:“bgsave 失敗的話,停止接收寫請求要怎麼配置?”

默認配置爲 stop-writes-on-bgsave-error yes,它的作用是如果 RDB 內存快照持久化開啓並且最後一次 bgsave 失敗的話就停止接收寫請求。

我通過這種強硬的方式來告知程序員數據持久化不正常了,否則可能沒人知道 RDB 快照持久化出問題了。

bgsave 後臺進程能正常工作,我會自動允許寫請求。如果你對此已經有相關的監控,即使磁盤出問題(磁盤空間不足、沒有權限等)的情況下依舊處理寫請求,那麼設置成 no 即可。

rdbcompression

MySQL:“RDB 內存快照文件比較大,可以壓縮麼?”

我的默認配置是 rdbcompression yes,意味着對 RDB 內存快照文件中的 String 對象使用 LZF 算法做壓縮。這個非常有用,能大大減少文件大小,受益匪淺呀,建議你開啓。

如果你不想損失因爲壓縮 RDB 內存快照文件的 CPU 資源,那就設置成 no,帶來的後果就是文件比較大,傳輸佔用更大的帶寬(要三思啊,老夥計)。

rdbchecksum

默認配置是 rdbchecksum yes,從 5.0 版本開始,RDB 文件末尾會寫入一個 CRC64 檢驗碼,能起到一定的糾錯作用,但是要丟失大約 10% 的性能損失,你可以設置成功 no 關閉這個功能來獲得更快的性能。

關閉了這個功能, RDB 內存快照文件的校驗就是 0 ,代碼會自動跳過檢查。

推薦你關閉,讓我快到令人髮指。

你還可以通過 dbfilename 參數來指定 RDB 內存快照文件名,默認是 dbfilename dump.rdb

rdb-del-sync-files

默認配置是 rdb-del-sync-files no,主從進行全量同步時,通過傳輸 RDB 內存快照文件實現,沒有開啓 RDB 持久化的實例在同步完成後會刪除該文件,通常情況下保持默認即可。

dir

我的工作目錄,注意這是目錄而不是文件, 默認配置是dir ./。比如存放 RDB 內存快照文件、AOF 文件。

5.5.3 主從複製

這部分配置很重要,涉及到主從複製的方方面面,是高可用的基石,重點對待啊夥計們。

replicaof

主從複製,使用replicaof <masterip> <masterport> 配置將當前實例成爲其他 Redis 服務的從節點

  • masterip,就是 master 的 IP。
  • masterport,master 的端口。

有以下幾點需要注意。

  • 我使用異步實現主從複製,當 Master 節點的 slave 節點數量小於指定的數量時,你可以設置 Master 節點停止處理寫請求。
  • 主從複製如果斷開的時間較短,slave 節點可以執行部分重新同步,需要合理設置 backlog size,保證這個緩存區能完整保存斷連期間 Master 接受寫請求的數據,防止出現全量複製,具體配置後面會細說。
  • 主從複製是自動的,不需要用戶干預。

masterauth

如果當前節點是 slave,且 master 節點配置了 requirepass 參數設置了密碼,那麼 slave 節點必須使用該參數配置爲 master 的密碼,否則 master 節點將拒絕該 slave 節點的請求。

配置方式爲 masterauth <master-password>

masteruser

在 6.0 以上版本,如果使用了我的 ACL 安全功能,只配置 masterauth 還不夠。因爲默認用戶不能運行 PSYNC 命令或者主從複製所需要的其他命令。

這時候,最好配置一個專門用於主從複製的特殊用戶,配置方式爲 masteruser <username>

replica-serve-stale-data

MySQL:“當 slave 節點與 master 失去連接,導致主從同步失敗的時候,還能處理客戶端請求麼?”

slave 節點可以有以下兩種行爲來決定是否處理客戶端請求。

  • 配置爲 yes,slave 節點可以繼續處理客戶端請求,但是數據可能是舊的,因爲新的沒同步過來。也可能是空的,如果是第一次同步的話。
  • 配置爲 no,slave 節點將返回錯誤 MASTERDOWN Link with MASTER is down and replica-serve-stale-data is set to no給客戶端。但是以下的指令還是可以執行:INFO, REPLICAOF, AUTH, SHUTDOWN, REPLCONF, ROLE, CONFIG, SUBSCRIBE,UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, COMMAND, POST,HOST and LATENCY

我的默認配置是 replica-serve-stale-data yes

replica-read-only

這個配置用於控制 slave 實例能否接收寫指令,在 2.6 版本後默認配置爲 yes,表示 slave 節點只處理讀請求,如果爲 no 則可讀可寫。

我建議保持默認配置,讓 slave 節點只作爲副本實現高可用。想要提高寫性能,使用集羣模式橫向拓展更好。

repl-diskless-sync

主從複製過程中,新加入的 slave 節點和 slave 節點重連後無法進行增量同步,需要進行一次全量同步,master 節點會生成 RDB 內存快照文件傳輸給 slave 節點。

所以這個配置是用於控制傳輸方式的,傳輸方式有兩種。

  • Disk-backed(磁盤備份):master 節點創建新進程將 RDB 內存快照文件寫到磁盤,主進程逐步將這個文件傳輸到不同 slave 節點。
  • Diskless(無盤備份):master 節點創建一個新進程直接把 RDB 內存快照內容寫到 Socket,不會將 RDB 內存快照文件持久化到磁盤。

使用磁盤備份的方式,master 保存在磁盤的 RDB 內存快照文件可以讓多個 slave 複用。

使用無盤備份的話,當 RDB 內存快照文件傳輸開始,如果當前有多個slave 節點與 master 建立連接,我會使用並行傳輸的方式將 RDB 內容傳輸給多個節點。

默認的配置是 repl-diskless-sync yes,表示使用無盤備份。在磁盤速度很慢,而網絡超快的情況下,無盤備份會更給力。如果網絡很慢,有可能會出現數據丟失,推薦你改成 no。

repl-diskless-sync-delay

使用無盤複製的話,如果此刻有新的 slave 發起全量同步,需要等待之前的傳輸完畢才能開啓傳輸。

所以可以使用配置 repl-diskless-sync-delay 5 參數指定一個延遲時間,這個單位是秒,讓 master 節點等待一會,讓更多 slave 節點連接再執行傳輸。

因爲一旦開始傳輸,master 節點無法響應新的 slave 節點的全量複製請求,只能在隊列中等待下一次 RDB 內存快照傳輸。

想要關閉這個功能,設置爲 0 即可。

repl-diskless-load

mastar 節點有兩種方式傳輸 RDB,slave 節點也有兩種方式加載 master 傳輸過來的 RDB 數據。

  • 傳統方式:接受到數據後,先持久化到磁盤,再從磁盤加載 RDB 文件恢復數據到內存中,這是傳統方式。
  • diskless-load:從 Socket 中一邊接受數據,一邊解析,實現無盤化。

一共有三個取值可配置。

  • disabled:不使用 diskless-load 方式,即採用磁盤化的傳統方式。
  • on-empty-db:安全模式下使用 diskless-load(也就 slave 節點數據庫爲空的時候使用 diskless-load)。
  • swapdb:使用 diskless-load 方式加載,slave 節點會緩存一份當前數據庫的數據,再清空數據庫,接着進行 Socket 讀取實現加載。緩存一份數據的目的是防止讀取 Socket 失敗。

需要注意的是,diskless-load 目前在實驗階段,因爲 RDB 內存快照數據並沒有持久化到磁盤,因此有可能造成數據丟失;

另外,該模式會佔用更多內存,可能會導致 OOM。

repl-ping-replica-period

默認配置repl-ping-replica-period 10 表示 slave 每 10 秒 PING 一次 master。

repl-timeout

很重要的一個參數,slave 與 master 之間的複製超時時間,默認配置是repl-timeout 60,表示在 60 秒內 ping 不通,則判定超時。

超時包含以下三種情況。

  • slave 角度,全量同步期間,在 repl-timeout 時間內沒有收到 master 傳輸的 RDB 內存快照文件。
  • slave 角度,在 repl-timeout 時間內沒有收到 master 發送的數據包或者 ping。
  • master 角度,在 repl-timeout 時間內沒有收到 REPCONF ACK (複製偏移量 offset)確認信息。

當檢測到超時,將會關閉 master 與 slave 之間的連接,slave 會發起重新建立主從連接的請求,對於內存數據比較大的系統,可以增大 repl-timeout 的值。

你需要注意的是,這個配置一定要大於 repl-ping-replica-period的值,否則每次心跳監測都超時。

repl-disable-tcp-nodelay

當 slave 與 master 全量同步(slave 發送 psync/sync 指令給 master)完成後,後續的增量同步是否設置成 TCP_NODELAY

如果設置成 yes,master 將合併小的 TCP 包從而節省帶寬,但是會增加同步延遲(40 ms),造成 master 與 slave 數據不一致;設置成 no,則 master 會立即發送數據給 slave,沒有延遲。

默認配置 repl-disable-tcp-nodelay no

repl-backlog-size

設置主從複製積壓緩衝區(backlog) 容量大小,這是一個環形數組,正常主從同步不涉及到 repl-backlog。當主從斷開重連,repl-backlog 的作用就出來了

緩衝區用於存放斷連期間 master 接受的寫請求數據,當主從斷開重連,通常不需要執行全量同步,只需要將斷連期間的部分數據傳遞到 slave 即可。

主從複製積壓緩衝區越大,slave 可以承受的斷連時間越長。

默認配置是 repl-backlog-size 1mb,建議根據每秒流量大小和斷開重連時間長,設置大一點,比如 128 mb。

repl-backlog-ttl

用於配置當 master 與 slave 斷連多少秒之後,master 清空主從複製積壓緩衝區(repl-backlog)。配置成 0 ,表示永遠不清空。默認配置repl-backlog-ttl 3600

replica-priority

slave 優先級,這個配置是給哨兵使用的,當 master 節點掛掉,哨兵會選擇一個 priority 最小的 slave 節點作爲新的 master,這個值越小沒接越優先選中。

如果是 0,那意味着這個 slave 將不能選中成爲 master,默認配置是 replica-priority 100

min-slaves-to-write 和 min-slaves-max-lag

這兩個配置要一起設置纔有意義,如果有一個配置成 0,表示關閉該特性。

先看默認配置含義。

min-replicas-to-write 3
min-replicas-max-lag 10

如果 master 發現超過 3 個 slave 節點連接 master 延遲大於 10 秒,那麼 master 就停止接收客戶端寫請求。這麼做的目的是爲了儘可能保證主從數據一致性。

master 會記錄每個 slave 最近一次發來 ping 的時間,掌握每個 slave 的運行情況。

tracking-table-max-keys

我在 Redis 6.0 版本,實現了服務端輔助實現客戶端緩存的特性,需要追蹤客戶端有哪些 key。當某個 key 被修改,我需要把這個失效信息發送到對應的客戶端將本地緩存失效,這個配置就是用於指定追蹤表保存的最大 key 數量,一旦超過這個數量,即使這個 key 沒有被修改,爲了回收內存我也會強制這個 key 所在的客戶端緩存值失效。

設置 0 表示不限制,需要注意的是,如果使用廣播模式實現鍵追蹤,則不需要額外內存,忽略這個配置。

使用廣播模式的不足就是與這個 key 無關的客戶端也會收到失效消息。

5.5.4 安全

正是由於我快的一塌糊塗,攻擊者一秒鐘可以嘗試 100 萬個密碼,所以你應該使用非常健壯的密碼。

ACL

ACL 日誌的最大長度,默認配置 acllog-max-len 128 表示最大 128 mb。

另外,使用 aclfile /etc/redis/users.acl 配置 ACL 文件所在位置。

requirepass

當前 Redis 服務器的訪問密碼,默認是不需要密碼訪問,網絡危險,必須設置,如 requirepass magebyte660設置密碼爲 “magebyte666”。

maxclients

設置客戶端同時連接的最大數量,默認設置是 maxclients 10000。達到最大值,我將關閉客戶端新的連接,併發送一個 max number of clients reached 錯誤給客戶端。

5.5.5 內存管理

作爲用內存保存數據的我,這部分的配置也相當重要。

maxmemory

設置使用內存最大字節,當內存達到限制,我將嘗試根據配置的內存淘汰策略(參見 maxmemory-policy)刪除一些 key。建議你不要設置太大的內存,防止執行 RDB 內存快照文件或者 AOF 重寫的時候因數據太大而阻塞過長時間。

推薦最大設置爲 maxmemory 6GB

如果淘汰策略是 noeviction,當收到寫請求,我將回復錯誤給客戶端,讀請求依然可以執行。

如果你把我當做一個 LRU 或 LFU 緩存系統的時候,那請用心關注以下配置。

maxmemory-policy

設置內存淘汰策略,定義當內存滿時如何淘汰 key,默認配置是 noeviction

  • volatile-lru -> 在設置過期時間的 key 中使用近似 LRU 驅逐。
  • allkeys-lru -> 在所有 key 中使用近似 LRU 驅逐。
  • volatile-lfu -> 在過期 key 中使用近似 LFU 驅逐。
  • allkeys-lfu -> 在所有 key 中使用近似 LFU。
  • volatile-random -> 在設置了過期時間的 key 中隨機刪除一個。
  • allkeys-random -> 在所有的 key 中隨機刪除一個。
  • volatile-ttl -> 誰快過期就刪誰。
  • noeviction -> 不刪除任何 key,內存滿了直接返回報錯。

maxmemory-samples

LRU, LFU and minimal TTL algorithms 不是精確的算法,是一個近似的算法(主要爲了節省內存)。

所以需要你自己權衡速度和精確度。默認會抽取 5 個 key,選擇一個最近最少使用的 key 淘汰,你可以改變這個數量。

默認的 5 可以提供不錯的結果。配置 10 會非常接近真實的 LRU 但是會耗費更多的 CPU,配置 3 會更快,但是就不那麼精確了。

replica-ignore-maxmemory

從 Redis 5.0 開始,默認情況下 slave 節點會忽略 maxmemory 配置,除非在故障轉移後或手動將其提升爲 master。這意味着只有 master 纔會執行內存淘汰策略,當 master 刪除 key 後會發送 DEL指令給 slave。

默認配置replica-ignore-maxmemory yes

active-expire-effort

我有兩種方式刪除過期數據。

  • 後臺週期性選取部分數據刪除。
  • 惰性刪除,當訪問請求到某個 key 的時候,發現該 key 已經過期則刪除。

這個配置用於指定過期 key 滯留在內存中的比例,默認值是 1,表示最多隻能有 10 % 的過期 key 駐留在內存中,值設置的越小,那麼一次淘汰週期內需需要消耗的 CPU 將會更多,因爲需要刪除更多的過期數據。

5.5.6 惰性釋放

MySQL:“ 可以使用非阻塞的方式刪除 bigkey 麼?”

我提供了兩種刪除 key 的基本命令用於刪除數據。

  • DEL 指令:這是一個阻塞的刪除,執行該指令會停止處理寫請求,使用同步的方式去回收 DEL 刪除的對象的內存。如果這個 key 對應的 value 是一個非常小的對象, DEL 執行的時間非常短,時間複雜度爲 O(1) 或者 O(log n)。如果 key 對應的 value 非常大,比如集合對象的數據包含百萬個元素,服務器將阻塞很長時間(幾秒鐘)才能完成操作。
  • UNLINK(非阻塞刪除)、(異步刪除) FLUSHALL ASYNC/FLUSHDB ASYNC:後臺回收內存,這些指令在常量級別時間內執行,會使用一個新的線程在後臺漸進的刪除並釋放內存(Lazy Free 機制)。

lazyfree-lazy-eviction

由於 maxmemory 和 maxmemory-policy 策略配置,我會刪除一些數據,防止內存爆掉。使用lazyfree-lazy-eviction yes表示使用 lazy free 機制,該場景開啓 lazy free 可能會導致淘汰數據的內存釋放不及時,出現內存超限。

lazyfree-lazy-expire

對於設置了 TTL 的鍵,過期後刪除。如果想啓用 lazy free 機制刪除,則配置 lazyfree-lazy-eviction yes

lazyfree-lazy-server-del

針對有些指令在處理已存在的鍵時,會帶有一個隱式的 DEL 鍵的操作。

rename 命令,當目標鍵已存在,我會先刪除目標鍵,如果這些目標鍵是一個 big key,那可能會出現阻塞刪除的性能問題。 此參數設置就是解決這類問題,建議配置 lazyfree-lazy-server-del yes 開啓。

replica-lazy-flush

該配置針對 slave 進行全量數據同步,在加載 master 的 RDB 內存快照文件之前,會先運行 flashall清理數據的時候是否採用異步 flush 機制。

推薦你使用 replica-lazy-flush yes配置,可減少全量同步耗時,從而減少 master 因輸出緩衝區暴漲引起的內存增長。

lazyfree-lazy-user-del

意思是是否將 DEL 指令的默認行爲替換成 lazy free 機制刪除,效果就跟 UNLINK 一樣,只要配置成 lazyfree-lazy-user-del yes

lazyfree-lazy-user-flush

FLUSHDB, FLUSHALL, SCRIPT FLUSH, FUNCTION FLUSH可以使用額外參數 ASYNC|SYNC 決定使用同步還是異步操作,當沒有指定這個可選項,可以通過 lazyfree-lazy-user-flush yes 表示使用異步刪除。

IO 多線程

大家知道我是單線程模型處理讀寫請求,但是有一些操作可以使用其他線程處理,比如 UNLINK,I/O 讀寫操作。

在 6.0 版本,我提供了 I/O 多線程處理 Socket 讀寫,利用 I/O 多線程可以提高客戶端 Socket 讀寫性能。

默認配置是關閉的,我只建議當你的機器至少是 4 核 CPU 或者更多的情況啓用,並且配置的線程數少於機器總 CPU 核數,配置超過 8 個線程對提升沒什麼幫助。

當你的機器是四核 CPU,那可以嘗試配置使用 2~3 個 I/O 線程,如果是 8 核 CPU,一般只需要配置 6 個線程。

如下配置表示開啓 I/O 線程組,線程組的 I/O 線程數量爲 3。

io-threads-do-reads yes
io-threads 3

5.5.7 AOF 持久化

除了 RDB 內存快照文件作爲持久化手段以外,還能使用 AOF(Append only file) 實現持久化,AOF 是一種可選的持久化策略提供更好數據安全性。

默認配置下,我最多隻會丟失一秒的數據,你甚至可以配置更高級別,最多隻丟失一次 write 操作,但這樣會對損耗性能。

appendonly

appendonly yes 表示開啓 AOF 持久化,可以同時開啓 AOF 和 RDB 內存快照持久化,如果開啓了 AOF ,我會先加載 AOF 用於恢復內存數據。

appendfilename

指定 AOF 文件名稱,默認名字是 appendonly.aof。爲了方便,你可以配置 appenddirname 指定 AOF 文件存儲目錄。

appendfsync

調用操作系統的 fsync()函數告訴操作系統把輸出緩衝區的數據持久化到磁盤, AOF 文件刷寫的頻率有三種。

  • no:不去主動調用 fsync(),讓操作系統自己決定何時寫磁盤。
  • always:每次 write 操作之後都調用 fsync(),非常慢,但是數據安全性最高。
  • everysec:每秒調用一次 fsync(),一個折中的策略,最多丟失一秒的數據。

默認配置是 appendfsync everysec,推薦大家這麼設置,兼顧了速度和數據安全。

no-appendfsync-on-rewrite

當 appendfsync 的配置設置成 always或者 everysec ,現在有一個後臺 save 進程(可能是生成 RDB 內存快照的 bgsave 進程,也有可能是 AOF rewrite 進程)正在進行大量的磁盤 I/O 操作,會造成調用 fsync()執行太長,後續其他想要調用 fsync() 的進程就會阻塞。

爲了緩解這個問題,可以使用以下配置 no-appendfsync-on-rewrite yes 表示當已經有 bgsavebgrewriteaof 後臺進程在調用 fsync() 時,不再開啓新進程執行 AOF 文件寫入。

這樣的話,就會出現當前有子進程在做 bgsave 或者其他的磁盤操作時,我就無法繼續寫 AOF 文件,這意味着可能會丟失更多數據。

如果有延遲問題,請將此選項改爲 yes。否則將其保留爲 no。從持久化的角度來看,no是最安全的選擇。

AOF 重寫

爲了防止 AOF 文件過大,antirez 大佬給我搞了個 AOF 重寫機制。

auto-aof-rewrite-percentage 100 表示當前 AOF 文件大小超過上一次重寫的 AOF 文件大小的百分之多少(如果沒有執行過 AOF 重寫,那就參照原始 AOF 文件大小),則執行 AOF 文件重寫操作。

除了這個配置,你還要配置 auto-aof-rewrite-min-size 64mb 用於指定觸發 AOF 重寫操作的文件大小。

如果該 AOF 文件大小小於該值,即使文件增長比例達到 100%,我也不會觸發 AOF 重寫操作,這是爲了防止 AOF 文件其實很小,但是滿足增長百分比時的多餘 AOF 重寫操作。

如果配置爲auto-aof-rewrite-percentage 0 ,表示禁用 AOF 重寫功能,建議大家開啓 AOF 重寫,防止文件過大。

aof-load-truncated

MySQL:如果 AOF 文件是損壞的,你還加載數據還原到內存中麼?

加載 AOF 文件把數據還原到內存中,文件可能是損壞的,比如文件末尾是錯誤的。這種情況一般是由於宕機導致,尤其是使用 ext4 文件系統掛載時沒配置 data=ordered 選項。

在這種情況下,我可以直接報錯,或者儘可能的讀取可讀的 AOF 內容。

如果配置成 aof-load-truncated yes,我依然會加載並讀取這個損壞的 AOF 文件,並記錄一個錯誤日誌通知程序員。

配置成 aof-load-truncated no,我就會報錯並拒絕啓動服務,你需要使用 redis-check-aof 工具修復 AOF 文件,再啓動 Redis。如果修復後還是錯誤,我依然報錯並拒絕啓動。

aof-use-rdb-preamble

這就是大名鼎鼎的 RDB-AOF 混合持久化功能,配置成 aof-use-rdb-preamble yes(必須先開啓 AOF),AOF 重寫生成的文件將同時包含 RDB 格式的內容和 AOF 格式內容。

混合持久化是在 AOF 重寫完成的,開啓混合持久化後,fork 出的子進程先將內存數據以 RDB 的方式寫入 AOF 文件,接着把 RDB 格式數據寫入 AOF 文件期間收到的增量命令從重寫緩衝區以 AOF 格式寫到文件中。

寫入完成後通知主進程更新統計信息,並把含有 RDB 格式和 AOF 格式的 AOF 文件替換舊的 AOF 文件。

這樣的好處是可以結合 RDB 和 AOF 的優點,實現快速加載同時避免丟失過多數據,缺點是 AOF 文件的 RDB 部分內容不是 AOF 格式,可讀性差(都是程序解析讀取,哪個傻瓜程序員去讀這個呀),強烈推薦你使用這個來保證持久化。

aof-timestamp-enabled

我在 7.0 版本新增的特性,大體就是講 AOF 現在支持時間戳了,你可以做到基於時間點來恢復數據。

默認是是 aof-timestamp-enabled no 表示關閉該特性,你可以按照實際需求選擇開啓。

5.5.7 Cluster 集羣

Redis Cluster 集羣相關配置,使用集羣方式的你必須重視和知曉。彆嘴上原理說的頭頭是道,而集羣有哪些配置?如何配置讓集羣快到飛起,實現真正的高可用卻一頭霧水,通過下面這些配置詳解也讓你對集羣原理更加深刻。

cluster-enabled

普通的 Redis 實例是不能成爲集羣的一員,想要將該節點加入 Redis Cluster,需要設置 cluster-enabled yes

cluster-config-file

cluster-config-file nodes-6379.conf 指定集羣中的每個節點文件。

集羣中的每個節點都有一個配置文件,這個文件並不是讓程序員編輯的,是我自己創建和更新的,每個節點都要使用不同的配置文件,一定要確保同一個集羣中的不同節點使用的是不同的文件。

cluster-node-timeout

設置集羣節點不可用的最大超時時間,節點失效檢測。集羣中當一個節點向另一個節點發送 PING 命令,但是目標節點未在給定的時限內返回 PING 命令的回覆時,那麼發送命令的節點會將目標節點標記爲 PFAIL(possible failuer,可能已失效);

如果 master 節點超過這個時間還是無響應,則用它的從節點將啓動故障遷移,升級成主節點。

默認配置是 cluster-node-timeout 15000,單位是毫秒數。

cluster-port

該端口是集羣總線監聽 TCP 連接的端口,默認配置爲 cluster-port 0,我就會把端口綁定爲客戶端命令端口 + 10000(客戶端端口默認 6379,所以綁定爲 16379 作爲集羣總線端口)。每個 Redis Cluster 節點都需要開放兩個端口:

  • 一個用於服務於客戶端的 TCP 端口,比如 6379.
  • 另一個稱爲集羣總線端口,節點使用集羣總線進行故障監測、配置更新、故障轉移等。客戶端不要與集羣總線端口通信,另外請確保在防火牆打開這兩個端口,否則 Redis 集羣之間將無法通信

cluster-replica-validity-factor

該配置用於決定當 Redis Cluster 集羣中,一個 master 宕機後,如何選擇一個 slave 節點完成故障轉移自動恢復(failover)。如果設置爲 0 ,則不管 slave 與 master 之間斷開多久,都有資格成爲 master。

下面提供了兩種方式來評估 slave 的數據是否太舊。

  • 如果有多個 slave 可以 failover,他們之間會通過交換信息選出擁有擁有最大複製 offset 的 slave 節點。
  • 每個 slave 節點計算上次與 master 節點交互的時間,這個交互包含最後一次 ping 操作、master 節點傳輸過來的寫指令、上次與 master 斷開的時間等。如果上次交互的時間過去很久,那麼這個節點就不會發起 failover。

針對第二點,交互時間可以通過配置定義,如果 slave 與 master 上次交互的時間大於 (node-timeout * cluster-replica-validity-factor) + repl-ping-replica-period,該 slave 就不會發生 failover。

例如,``node-timeout = 30秒,cluster-replica-validity-factor=10repl-ping-slave-period=10`秒, 表示 slave 節點與 master 節點上次交互時間已經過去了 310 秒,那麼 slave 節點就不會做 failover。

調大 cluster-replica-validity-factor 則允許存儲過舊數據的 slave 節點提升爲 master,調小的話可能會導致沒有 slave 節點可以升爲 master 節點。

考慮高可用,建議大家設置爲 cluster-replica-validity-factor 0

cluster-migration-barrier

沒有 slave 節點的 master 節點稱爲孤兒 master 節點,這個配置就是用於防止出現孤兒 master。

當某個 master 的 slave 節點宕機後,集羣會從其他 master 中選出一個富餘的 slave 節點遷移過來,確保每個 master 節點至少有一個 slave 節點,防止當孤立 master 節點宕機時,沒有 slave 節點可以升爲 master 導致集羣不可用。

默認配置爲 cluster-migration-barrier 1,是一個遷移臨界值。

含義是:被遷移的 master 節點至少還有 1 個 slave 節點才能做遷移操作。比如 master A 節點有 2 個以上 slave 節點 ,當集羣出現孤兒 master B 節點時,A 節點富餘的 slave 節點可以遷移到 master B 節點上。

生產環境建議維持默認值,最大可能保證高可用,設置爲非常大的值或者配置 cluster-allow-replica-migration no 禁用自動遷移功能。

cluster-allow-replica-migration 默認配置爲 yes,表示允許自動遷移。

cluster-require-full-coverage

默認配置是 yes,表示爲當 redis cluster 發現還有哈希槽沒有被分配時禁止查詢操作。

這就會導致集羣部分宕機,整個集羣就不可用了,當所有哈希槽都有分配,集羣會自動變爲可用狀態。

如果你希望 cluster 的子集依然可用,配置成 cluster-require-full-coverage no

cluster-replica-no-failover

當配置成 yes,在 master 宕機時,slave 不會做故障轉移升爲 master。

這個配置在多數據中心的情況下會很有用,你可能希望某個數據中心永遠不要升級爲 master 節點,否則 master 節點就漂移到其他數據中心了,正常情況設置成 no。

cluster-allow-reads-when-down

默認是 no,表示當集羣因主節點數量達不到最小值或者哈希槽沒有完全分配而被標記爲失效時,節點將停止所有客戶端請求。

設置成 yes,則允許集羣失效的情況下依然可從節點中讀取數據,保證了高可用。

cluster-allow-pubsubshard-when-down

配置成 yes,表示當集羣因主節點數量達不到最小值或者哈希槽沒有完全分配而被標記爲失效時,pub/sub 依然可以正常運行。

設置每個集羣總線連接的發送字節緩衝區的內存使用限制,超過限制緩衝區將被清空(主要爲了防止發送緩衝區發送給慢速連接時無限延長時間的問題)。

默認禁用,建議最小設置 1gb,這樣默認情況下集羣連接緩衝區可以容納至少一條 pubsub 消息(client-query-buffer-limit 默認是 1gb);

5.5.8 性能監控

慢查詢日誌

慢查詢(Slow Log)日誌是我用於記錄慢查詢執行時間的日誌系統,只要查詢超過配置的時間,都會記錄。slowlog 只保存在內存中,因此效率很高,大家不用擔心會影響到 Redis 的性能。

執行時間不包括 I/O 操作的時間,比如與客戶端建立連接、發送回覆等,只記錄執行命令執行階段所需要的時間。

你可以使用兩個參數配置慢查詢日誌系統。

  • slowlog-log-slower-than:指定對執行時間大於多少微秒(microsecond,1 秒 = 1,000,000 微秒)的查詢進行記錄,默認是 10000 微妙,推薦你先執行基線測試得到一個基準時間,通常這個值可以設置爲基線性能最大延遲的 3 倍。
  • slowlog-max-len:設定最多保存多少條慢查詢的日誌,slowlog 本身是一個 FIFO 隊列,當超過設定的最大值後,我會把最舊的一條日誌刪除。默認配置 128,如果設置太大會佔用多大內存。

延遲監控

延遲監控(LATENCY MONITOR)系統會在運行時抽樣部分命令來幫助你分析 Redis 卡頓的原因。

通過 LATENCY命令,可以打印一些視圖和報告,系統只會記錄大於等於指定值的命令。

默認配置 latency-monitor-threshold 0,設置 0 表示關閉這個功能。沒有延遲問題,沒必要開啓開啓監控,因爲會對性能造成很大影響。

在運行過程中你懷疑有延遲性能問題,想要監控的話可以使用 CONFIG SET latency-monitor-threshold <milliseconds>開啓,單位是毫秒。

5.5.9 高級設置

這部分配置主要圍繞以下幾個方面。

  • 指定不同數據類型根據不同條數下使用不同的數據結構存儲,合理配置能做到更快和更省內存。
  • 客戶端緩衝區相關配置。
  • 漸進式 rehash 資源控制。
  • LFU 調優。
  • RDB 內存快照文件、AOF 文件同步策略。

Hashes(散列表)

在 Redis 7.0 版本散列表數據類型有兩種數據結構保存數據,分別爲散列表和 listpack。當數據量很小時,可以使用更高效的數據結構存儲,從而達到在不影響性能的情況下節省內存。

  • hash-max-listpack-entries 512:指定使用 listpack 存儲的最大條目數。
  • hash-max-listpack-value 64:listpack 中,條目 value 值最大字節數,建議設置成 1024。

在 7.0 版本以前,使用的是 ziplist 數據結構,配置如下。

hash-max-ziplist-entries 512
hash-max-ziplist-value 64

Lists(列表)

Lists 也可以使用一種特殊方式進行編碼來節省大量內存空間。在 Redis 7.0 之後,Lits 底層的數據結構使用 linkedlist 或者 listpack 。

Redis 3.2 版本,List 內部是通過 linkedlist 和 quicklist 實現,quicklist 是一個雙向鏈表, quicklist 的每個節點都是一個 ziplist,從而實現節省內存。

元素少時用 quicklist,元素多時用 linkedlist。listpack 的目的就是用於替代 ziplist 和 quicklist。listpack 也叫緊湊列表,它的特點就是用一塊連續的內存空間來緊湊地保存數據,同時爲了節省內存空間

list-max-ziplist-size

7.0 版本之前list-max-ziplist-size 用於配置 quicklist 中的每個節點的 ziplist 的大小。 當這個值配置爲正數時表示 quicklist 每個節點的 ziplist 最多可存儲元素數量,超過該值就會使用 linkedlist 存儲。

list-max-ziplist-size 爲負數時表示限制每個 quicklistNode 的 ziplist 的內存大小,超過這個大小就會使用 linkedlist 存儲數據,每個值有以下含義:

  • -5:每個 quicklist 節點上的 ziplist 大小最大 64 kb <--- 正常環境不推薦
  • -4:每個 quicklist 節點上的 ziplist 大小最大 32 kb <--- 不推薦
  • -3:每個 quicklist 節點上的 ziplist 大小最大 16 kb <--- 可能不推薦
  • -2:每個 quicklist 節點上的 ziplist 大小最大 8 kb <--- 不錯
  • -1:每個 quicklist 節點上的 ziplist 大小最大 4kb <--- 不錯

默認值爲 -2,也是官方最推薦的值,當然你可以根據自己的實際情況進行修改。

list-max-listpack-size

7.0 之後,配置修改爲list-max-listpack-size -2則表示限制每個 listpack 大小,不再贅述。

list-compress-depth

壓縮深度配置,用來配置壓縮 Lists 的,當 Lists 底層使用 linkedlist 也是可以壓縮的,默認是 list-compress-depth 0表示不壓縮。一般情況下,Lists 的兩端訪問的頻率高一些,所以你可以考慮把中間的數據進行壓縮。

不同參數值的含義如下。

  • 0,關閉壓縮,默認值。
  • 1,兩端各有一個節點不壓縮。
  • 2,兩端各有兩個節點不壓縮。
  • N,依次類推,兩端各有 N 個節點不壓縮。

需要注意的是,head 和 tail 節點永遠都不會被壓縮。

Sets(無序集合)

Sets 底層的數據結構可以是 intset(整形數組)和 Hashtable(散列表),intset 你可以理解成數組,Hashtable 就是普通的散列表(key 存的是 Sets 的值,value 爲 null)。有沒有覺得 Sets 使用散列表存儲是意想不到的事情?

set-max-intset-entries

當集合的元素都是 64 位以內的十進制整數時且長度不超過 set-max-intset-entries 配置的值(默認 512),Sets 的底層會使用 intset 存儲節省內存。添加的元素大於 set-max-intset-entries配置的值,底層實現由 intset 轉成散列表存儲。

SortedSets(有序集合)

在 Redis 7.0 版本之前,有序集合底層的數據結構有 ziplist 和 skipist,之後使用 listpack 代替了 ziplist。

7.0 版本之前,當集合元素個數小於 zset-max-ziplist-entries配置,同時且每個元素的值大小都小於zset-max-ziplist-value配置(默認 64 字節,推薦調大到 128)時,我將使用 ziplist 數據結構存儲數據,有效減少內存使用。與此類似,7.0 版本之後我將使用 listpack 存儲。

## 7.0 之前的配置
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
## 7.0 之後的配置
zset-max-listpack-entries 128
zset-max-listpack-value 64

HyperLogLog

HyperLogLog 是一種高級數據結構,統計基數的利器。HyperLogLog 的存儲結構分爲密集存儲結構和稀疏存儲結構兩種,默認爲稀疏存儲結構,而我們常說的佔用 12K 內存的則是密集存儲結構,稀疏結構佔用的內存會更小。

hll-sparse-max-bytes

默認配置是 hll-sparse-max-bytes 3000,單位是 Byte,這個配置用於決定存儲數據使用稀疏數據結構(sparse)還是稠密數據結構(dense)。

如果 HyperLogLog 存儲內容大小大於 hll-sparse-max-bytes 配置的值將會轉換成稠密的數據結構(dense)。

推薦的值是 0~3000,這樣PFADD命令的並不會慢多少,還能節省空間。如果內存空間相對 cpu 資源更缺乏,可以將這個值提升到 10000。

Streams(流)

Stream 是 Redis 5.0 版本新增的數據類型。Redis Streams 是一些由基數樹(Radix Tree)連接在一起的節點經過 delta 壓縮後構成的,這些節點與 Stream 中的消息條目(Stream Entry)並非一一對應,而是每個節點中都存儲着若干 Stream 條目,因此這些節點也被稱爲宏節點或大節點。

stream-node-max-bytes 4096

單位爲 Byte,默認值 4096,用於設定每個宏節點佔用的內存上限爲 4096,0 表示無限制。

stream-node-max-entries 100

用於設定每個宏節點存儲元素個數。 默認值 100,0 表示無限制。當一個宏節點存儲的 Stream 條目到達上限,新添加的條目會存儲到新的宏節點中。

rehash

我採用的是漸進式 rehash,這是一個惰性策略,不會一次性把所有數據遷移完,而是分散到每次請求中,這樣做的目的是防止數據太多要遷移阻塞主線程。

在漸進式 rehash 的同時,推薦你使用 activerehashing yes開啓定時輔助執行 rehash,默認情況下每一秒執行 10 次 rehash 加快遷移速度,儘可能釋放內存。

關閉該功能的話,如果這些 key 不再活躍不被被訪問到,rehash 操作可能不再有機會完成,會導致散列表佔用更多內存。

客戶端輸出緩衝區限制

這三個配置是用來強制斷開客戶端連接的,當客戶端沒有及時把緩衝區的數據讀取完畢,我會認爲這個客戶端可能完蛋了(一個常見的原因是 Pub/Sub 客戶端處理髮布者的消息不夠快),於是斷開連接。

一共分爲三種不同類型的客戶端,分別設置不同的限制。

  • normal(普通),普通客戶端,包括 MONITOR 客戶端。
  • replica(副本客戶端),slave 節點的客戶端。
  • pubsub(發佈訂閱客戶端),至少訂閱了一個 pubsub 頻道或者模式的客戶端。

client-output-buffer-limit的語法如下。

client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>

表示不同類型的客戶端,當客戶端的緩衝區內容大小達到 後我就立馬斷開與這個客戶端的連接,或者達到 並持續了 秒後斷開。

默認情況下,普通客戶端不會限制,只有後異步的客戶端纔可能發送發送請求的速度比讀取響應速度快的問題。比如 pubsub 和 replica 客戶端會有默認的限制。

soft limit 或者 hard limit 設置爲 0,表示不啓用此限制。默認配置如下。

client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

client-query-buffer-limit

每個客戶端都有一個 query buffer(查詢緩衝區或輸入緩衝區),用於保存客戶端發送命令,Redis Server 從 query buffer 獲取命令並執行。

如果程序的 Key 設計不合理,客戶端使用大量的 query buffer,導致 Redis 很容易達到 maxmeory 限制。最好限制在一個固定的大小來避免佔用過大內存的問題。

如果你需要發送巨大的 multi/exec 請求的時候,那可以適當修改這個值以滿足你的特殊需求。

默認配置爲 client-query-buffer-limit 1gb

maxmemory-clients

這是 7.0 版本特性,每個與服務端建立連接的客戶端都會佔用內存(查詢緩衝區、輸出緩衝區和其他緩衝區),大量的客戶端可能會佔用過大內存導致 OOM,爲了避免這個情況,我提供了一種叫做(Client Eviction)客戶端驅逐機制用於限制內存佔用。

配置方式有兩種。

  • 具體內存值, maxmemory-clients 1g來限制所有客戶端佔用內存總和。
  • 百分比,maxmemory-clients 5% 表示客戶端總和內存佔用最多爲 Redis 最大內存配置的 5%。

默認配置是 maxmemory-clients 0 表示無限制。

MySQL:“達到最大內存限制,你會把所有客戶端連接都釋放麼?”

不是的,一旦達到限制,我會優先嚐試斷開使用內存最多的客戶端。

proto-max-bulk-len

批量請求(單個字符串的元素)內存大小限制,默認是 proto-max-bulk-len 512mb,你可以修改限制,但必須大於等於 1mb。

hz

我會在後臺調用一些函數來執行很多後臺任務,比如關閉超時連接,清理不再被請求的過期的 key,rehash、執行 RDB 內存快照和 AOF 持久化等。

並不是所有的後臺任務都需要使用相同的頻率來執行,你可以使用 hz 參數來決定執行這些任務的頻率。

默認配置是 hz 10,表示每秒執行 10 次,更大的值會消耗更多的 CPU 來處理後臺任務,帶來的效果就是更快的清理過期 key,清理的超時連接更精確。

這個值的範圍是 1~500,不過並不推薦設置大於 100 的值。大家使用默認值就好,或者最多調高到 100。

dynamic-hz

默認配置是 dynamic-hz yes,啓用 dynamic-hz 後,將啓用自適應 HZ 值的能力。hz 的配置值將會作爲基線,Redis 服務中的實際 hz 值會在基線值的基礎上根據已連接到 Redis 的客戶端數量自動調整,連接的客戶端越多,實際 hz 值越高,Redis 執行定期任務的頻率就越高。

aof-rewrite-incremental-fsync

當子進程進行 AOF 重寫時,如果配置成 aof-rewrite-incremental-fsync yes,每生成 4 MB 數據就執行一次 fsync操作,分批提交到硬盤來避免高延遲峯值,推薦開啓。

rdb-save-incremental-fsync

當我在保存 RDB 內存快照文件時,如果配置成 db-save-incremental-fsync yes,每生成 4MB 文件就執行一次 fsync操作,分批提交到硬盤來避免高延遲峯值,推薦開啓。

LFU 調優

這個配置生效的前提是內存淘汰策略設置的是 volatile-lfuallkeys-lfu

  • lfu-log-factor 用於調整 Logistic Counter 的增長速度,lfu-log-factor 值越大,Logistic Counter 增長越慢。默認配置 10。

    以下是表格是官方不同 factor 配置下,計數器的改變頻率。注意:表格是通過如下命令獲得的: redis-benchmark -n 1000000 incr foo redis-cli object freq foo

    factor 100 hits 1000 hits 100K hits 1M hits 10M hits
    0 104 255 255 255 255
    1 18 49 255 255 255
    10 10 18 142 255 255
    100 8 11 49 143 255
  • lfu-decay-time 用於調整 Logistic Counter 的衰減速度,它是一個以分鐘爲單位的數值,默認值爲 1;lfu-decay-time 值越大,衰減越慢。

5.5.9 在線內存碎片整理

MySQL:“什麼是在線內存碎片整理?”

Active (online) defragmentation 在線內存碎片整理指的是自動壓縮內存分配器分配和 Redis 頻繁做更新操作、大量過期數據刪除,釋放的空間(不夠連續)無法得到複用的內存空間。

通常來說當碎片化達到一定程度(查看下面的配置)Redis 會使用 Jemalloc 的特性創建連續的內存空間, 並在此內存空間對現有的值進行拷貝,拷貝完成後會釋放掉舊的數據。 這個過程會對所有的導致碎片化的 key 以增量的形式進行。

需要注意的是

  1. 這個功能默認是關閉的,並且只有在編譯 Redis 時使用我們代碼中的 Jemalloc 版本才生效。(這是 Linux 下的默認行爲)。
  2. 在實際使用中,建議是在 Redis 服務出現較多的內存碎片時啓用(內存碎片率大於 1.5),正常情況下儘量保持禁用狀態。
  3. 如果你需要試驗這項特性,可以通過命令 CONFIG SET activefrag yes來啓用。

清理的條件

activefrag yes:內存碎片整理總開關,默認爲禁用狀態 no。

active-defrag-ignore-bytes 200mb:內存碎片佔用的內存達到 200MB。

active-defrag-threshold-lower 20:內存碎片的空間佔比超過系統分配給 Redis 空間的 20% 。

在同時滿足上面三項配置時,內存碎片自動整理功能纔會啓用。

CPU 資源佔用

MySQL:如何避免自動內存碎片整理對性能造成影響?

清理的條件有了,還需要分配清理碎片佔用的 CPU 資源,保證既能正常清理碎片,又能避免對 Redis 處理請求的性能影響。

active-defrag-cycle-min 5:自動清理過程中,佔用 CPU 時間的比例不低於 5%,從而保證能正常展開清理任務。

active-defrag-cycle-max 20:自動清理過程佔用的 CPU 時間比例不能高於 20%,超過的話就立刻停止清理,避免對 Redis 的阻塞,造成高延遲。

整理力度

active-defrag-max-scan-fields 1000:碎片整理掃描到set/hash/zset/list 時,僅當 set/hash/zset/list的長度小於此閥值時,纔會將此鍵值對加入碎片整理,大於這個值的鍵值對會放在一個列表中延遲處理。

active-defrag-threshold-upper 100:內存碎片空間佔操作系統分配給 Redis 的總空間比例達此閾值(默認 100%),我會盡最大努力整理碎片。建議你調整爲 80。

jemalloc-bg-thread

默認配置爲 jemalloc-bg-thread yes,表示啓用清除髒頁後臺線程。

綁定 CPU

你可以將 Redis 的不同線程和進程綁定到特定的 CPU,減少上下文切換,提高 CPU L1、L2 Cache 命中率,實現最大化的性能。

你可以通過修改配置文件或者taskset命令綁定。

可分爲三個模塊。

  • 主線程和 I/O 線程:負責命令讀取、解析、結果返回。命令執行由主線程完成。
  • bio 線程:負責執行耗時的異步任務,如 close fd、AOF fsync 等。
  • 後臺進程:fork 子進程(RDB bgsave、AOF rewrite bgrewriteaof)來執行耗時的命令。

Redis 支持分別配置上述模塊的 CPU 親合度,默認情況是關閉的。

  • server_cpulist 0-7:2,I/O 線程(包含主線程)相關操作綁定到 CPU 0、2、4、6。
  • bio_cpulist 1,3,bio 線程相關的操作綁定到 CPU 1、3。
  • aof_rewrite_cpulist,aof rewrite 後臺進程綁定到 CPU 8、9、10、11。
  • bgsave_cpulist 1,10-11,bgsave 後臺進程綁定到 CPU 1、10、11。

注意事項

  1. Linux 下,使用 「numactl --hardware」 查看硬件佈局,確保支持並開啓 NUMA。
  2. 線程要儘可能分佈在 不同的 CPU,相同的 node,設置 CPU 親和度纔有效,否則會造成頻繁上下文切換。
  3. 你要熟悉 CPU 架構,做好充分的測試。否則可能適得其反,導致 Redis 性能下降。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章