Redis.Conf 7.0 配置和原理全解,生產(chǎn)王者必備
我是 Redis, 當(dāng)程序員用指令 ./redis-server /path/to/redis.conf 把我啟動(dòng)的時(shí)候,第一個(gè)參數(shù)必須是redis.conf 文件的路徑。
這個(gè)文件很重要,就好像是你們的 DNA,它能控制我的運(yùn)行情況,不同的配置會(huì)有不同的特性和人生,它掌握我的人生命運(yùn),控制著我如何完成高可用、高性能。合理的配置能讓我更快、更省內(nèi)存,并發(fā)揮我最大的優(yōu)勢(shì)讓我更安全運(yùn)行。
以下這些配置大家必知必會(huì),需要大家掌握每個(gè)配置背后的技術(shù)原理,學(xué)會(huì)融合貫通并在生產(chǎn)中正確配置,解決問題。避免出現(xiàn)技術(shù)懸浮,原理說的叭叭叭,配置像個(gè)大傻瓜。
本文配置文件版本是 Redis 7.0。
1.1 常規(guī)通用配置
這些是我的常規(guī)配置,每個(gè) Redis 啟動(dòng)必備參數(shù),你一定要掌握,涉及到網(wǎng)絡(luò)、模塊插件、運(yùn)行模式、日志等。
MODULES
這個(gè)配置可以加載模塊插件增強(qiáng)我的功能,常見的模塊有 RedisSearch、RedisBloom 等。關(guān)于模塊加載可以參考【5.6 布隆過濾器原理與實(shí)戰(zhàn)】章節(jié)集成布隆過濾器便是通過以下配置實(shí)現(xiàn)加載布隆過濾器插件。
NETWORK
這部分都是與網(wǎng)絡(luò)相關(guān)的配置,很重要滴,配置不當(dāng)將會(huì)有安全和性能問題。
bind
bind用于綁定本機(jī)的網(wǎng)絡(luò)接口(網(wǎng)卡),注意是本機(jī)。
每臺(tái)機(jī)器可能有多個(gè)網(wǎng)卡,每個(gè)網(wǎng)卡都有一個(gè) IP 地址。配置了 bind,則表示我只允許來自本機(jī)指定網(wǎng)卡的 Redis 請(qǐng)求。
MySQL:“bind 是用于限制訪問你的機(jī)器 IP 么?”
非也,注意,這個(gè)配置指的并不是只有 bind 指定的 IP 地址的計(jì)算機(jī)才能訪問我。如果想限制指定的主機(jī)連接我,只能通過防火墻來控制,bind 參數(shù)不也能起到這個(gè)作用。
舉個(gè)例子:如果我所在的服務(wù)器有兩個(gè)網(wǎng)卡,每個(gè)網(wǎng)卡有一個(gè) IP 地址, IP1,IP2。
配置 bind IP1,則表示只能通過這個(gè)網(wǎng)卡地址來的網(wǎng)絡(luò)請(qǐng)求訪問我,也可以使用空格分割綁定多個(gè)網(wǎng)卡 IP。
我的默認(rèn)配置是bind 127.0.0.1 -::1 表示綁定本地回環(huán)地址 IPv4 和 Ipv6。- 表示當(dāng) ip 不存在也能啟動(dòng)成功。
protected-mode
MySQL:網(wǎng)絡(luò)世界很危險(xiǎn)滴,你如何保證安全?
默認(rèn)開啟保護(hù)模式,如果沒有設(shè)置密碼或者沒有 bind 配置,我只允許在本機(jī)連接我,其它機(jī)器無法連接。
如果想讓其它機(jī)器連接我,有以下三種方式。
- 配置為protected-mode no(不建議,地球很危險(xiǎn)滴,防人之心不可無)。
- protected-mode yes,配置 bind 綁定本機(jī)的 IP。
- protected-mode yes,除了設(shè)置 bind 以外,還可以通過 requirepass magebyte設(shè)置密碼為 magebyte, 讓其他機(jī)器的客戶端能使用密碼訪問我。
bind、protected-mode、requirepass 之間的關(guān)系
- bind:指定的是我所在服務(wù)器網(wǎng)卡的 IP,不是指定某個(gè)可以訪問我的機(jī)器。
- protected-mode:保護(hù)模式,默認(rèn)開啟,如果沒有設(shè)置密碼或者 bind IP,我只接受本機(jī)訪問(沒密碼+保護(hù)模式啟動(dòng)=本地訪問)。
- requirepass,Redis 客戶端連接我通行的密碼。
如果參數(shù)設(shè)置為bind 127.0.0.1 -::1,不管 protected-mode是否開啟,只能本機(jī)用 127.0.0.1 連接,其他外機(jī)無法連接。
在生產(chǎn)環(huán)境中,為了安全,不要關(guān)閉 protected-mode,并設(shè)置 requirepass 參數(shù)配置密碼和 bind 綁定機(jī)器的網(wǎng)卡 IP。
port 6379
用于指定我監(jiān)聽的客戶端 socket 端口號(hào),默認(rèn) 6379。設(shè)置為 0 則不會(huì)監(jiān)聽 TCP 連接,我想沒人設(shè)置為 0 吧。
tcp-backlog 511
用于在 Linux 系統(tǒng)中控制 TCP 三次握手已完成連接隊(duì)列(完成三次握手后)的長(zhǎng)度,如果已完成連接隊(duì)列已經(jīng)滿則無法放入,客戶端會(huì)報(bào)read timeout或者connection reset by peer的錯(cuò)。
MySQL:“在高并發(fā)系統(tǒng)中這玩意需要調(diào)大些吧?”
是的,我的默認(rèn)配置是 511,這個(gè)配置的值不能大于 Linux 系統(tǒng)定義的 /proc/sys/net/core/somaxconn 值,Linux 默認(rèn)的是 128。
所以我在啟動(dòng)的時(shí)候你會(huì)看到這樣的警告:WARNING: The TCP backlog setting of 511 cannot be enforced because kern.ipc.somaxconn is set to the lower value of 128.
當(dāng)系統(tǒng)并發(fā)量大并且客戶端速度緩慢的時(shí)候,在高并發(fā)系統(tǒng)中,需要設(shè)置一個(gè)較高的值來避免客戶端連接速度慢的問題。
需要分別調(diào)整 Linux 和 Redis 的配置。
建議修改為 2048 或者更大,Linux 則在 /etc/sysctl.conf中添加net.core.somaxconn = 2048配置,并且在終端執(zhí)行 sysctl -p即可。
碼哥使用 macOS 系統(tǒng),使用 sudo sysctl -w kern.ipc.somaxconn=2048即可。
timeout
timeout 60 單位是秒,如果在 timout 時(shí)間內(nèi)客戶端跟我沒有數(shù)據(jù)交互(客戶端不再向我發(fā)送任何數(shù)據(jù)),我將關(guān)閉該客戶端連接。
注意事項(xiàng)
- 0 表示永不斷開。
- timeout 對(duì)應(yīng)源碼server.maxidletime
tcp-keepalive
tcp-keepalive 300 單位是秒,官方建議值是 300。這是一個(gè)很有用的配置,實(shí)現(xiàn) TCP 連接復(fù)用。
用途
用于客戶端與服務(wù)端的長(zhǎng)連接,如果設(shè)置為非 0,則使用 SO_KEEPALIVE 周期性發(fā)送 ACK 給客戶端,俗話就是用來定時(shí)向客戶端發(fā)送 tcp_ack 包來探測(cè)客戶端是否存活,并保持該連接。不用每次請(qǐng)求都建立 TCP 連接,畢竟創(chuàng)建連接是比較慢的。
常規(guī)配置
這些都是我的常規(guī)配置,比較通用,你必須了解。你可以把這些配置寫到一個(gè)特有文件中,其他節(jié)點(diǎn)可以使用 include /path/to/other.conf 配置來加載并復(fù)用該配置文件的配置。
daemonize
配置daemonize yes表示使用守護(hù)進(jìn)程的模式運(yùn)行,默認(rèn)情況下我是以非守護(hù)線程的模式運(yùn)行(daemonize no),開啟守護(hù)進(jìn)程模式,會(huì)生成一個(gè) .pid文件存儲(chǔ)進(jìn)程號(hào)。
你也可以配置 pidfile /var/run/redis_6379.pid 參數(shù)來指定文件的生成目錄,當(dāng)關(guān)閉服務(wù)的時(shí)候我會(huì)自動(dòng)刪除該文件。
loglevel
指定我在運(yùn)行時(shí)的日志記錄級(jí)別。默認(rèn)是 loglevel notice。有以下幾個(gè)選項(xiàng)可以配置。
- debug:會(huì)記錄很多信息,主要用于開發(fā)和測(cè)試。
- verbose:許多用處不大的信息,但是比 debug 少,如果發(fā)現(xiàn)生產(chǎn)出現(xiàn)一些問題無從下手,可使用該級(jí)別來輔助定位。
- notice:生產(chǎn)一般配置這個(gè)級(jí)別。
- warning:只會(huì)記錄非常重要/關(guān)鍵的的日志。
logfile
指定日志文件目錄,默認(rèn)是 logfile "",表示只在標(biāo)準(zhǔn)控制臺(tái)輸出。
需要注意的是,如果使用標(biāo)準(zhǔn)控制臺(tái)輸出,并且使用守護(hù)進(jìn)程的模式運(yùn)行,日志會(huì)發(fā)送到 /dev/null。
databases
設(shè)置數(shù)據(jù)庫數(shù)量,我的默認(rèn)配置是 databases 16 。默認(rèn)的數(shù)據(jù)庫是 DB 0,使用集群模式的時(shí)候, database 只有一個(gè),就是 DB 0。
1.2 RDB 快照持久化
MySQL:“要怎么開啟 RDB 內(nèi)存快照文件實(shí)現(xiàn)持久化呢?”
RDB 快照持久化相關(guān)的配置,必須掌握,合理配置能我實(shí)現(xiàn)宕機(jī)快速恢復(fù)實(shí)現(xiàn)高可用。
save
使用 save <seconds> <changes> 開啟持久化,比如 save 60 100 表示 60 秒內(nèi),至少執(zhí)行了 100 個(gè)寫操作,則執(zhí)行 RDB 內(nèi)存快照保存。
不關(guān)心是否丟失數(shù)據(jù),你也可以通過配置 save "" 來禁用 RDB 快照保存,讓我性能起飛,沖出三界外。
默認(rèn)情況的我會(huì)按照如下規(guī)則來保存 RDB 內(nèi)存快照。
- 在 3600 秒 (一個(gè)小時(shí)) 內(nèi),至少執(zhí)行了一次更改。
- 在 300 秒(5 分鐘)內(nèi),至少執(zhí)行了 100 個(gè)更改。
- 在 60 秒后,至少執(zhí)行了 10000 個(gè)更改。
也可以通過 save 3600 1 300 100 60 10000 配置來顯示設(shè)置。
stop-writes-on-bgsave-error
MySQL:“bgsave 失敗的話,停止接收寫請(qǐng)求要怎么配置?”
默認(rèn)配置為 stop-writes-on-bgsave-error yes,它的作用是如果 RDB 內(nèi)存快照持久化開啟并且最后一次 bgsave 失敗的話就停止接收寫請(qǐng)求。
我通過這種強(qiáng)硬的方式來告知程序員數(shù)據(jù)持久化不正常了,否則可能沒人知道 RDB 快照持久化出問題了。
當(dāng) bgsave 后臺(tái)進(jìn)程能正常工作,我會(huì)自動(dòng)允許寫請(qǐng)求。如果你對(duì)此已經(jīng)有相關(guān)的監(jiān)控,即使磁盤出問題(磁盤空間不足、沒有權(quán)限等)的情況下依舊處理寫請(qǐng)求,那么設(shè)置成 no 即可。
rdbcompression
MySQL:“RDB 內(nèi)存快照文件比較大,可以壓縮么?”
我的默認(rèn)配置是 rdbcompression yes,意味著對(duì) RDB 內(nèi)存快照文件中的 String 對(duì)象使用 LZF 算法做壓縮。這個(gè)非常有用,能大大減少文件大小,受益匪淺呀,建議你開啟。
如果你不想損失因?yàn)閴嚎s RDB 內(nèi)存快照文件的 CPU 資源,那就設(shè)置成 no,帶來的后果就是文件比較大,傳輸占用更大的帶寬(要三思啊,老伙計(jì))。
rdbchecksum
默認(rèn)配置是 rdbchecksum yes,從 5.0 版本開始,RDB 文件末尾會(huì)寫入一個(gè) CRC64 檢驗(yàn)碼,能起到一定的糾錯(cuò)作用,但是要丟失大約 10% 的性能損失,你可以設(shè)置成功 no 關(guān)閉這個(gè)功能來獲得更快的性能。
關(guān)閉了這個(gè)功能, RDB 內(nèi)存快照文件的校驗(yàn)就是 0 ,代碼會(huì)自動(dòng)跳過檢查。
推薦你關(guān)閉,讓我快到令人發(fā)指。
你還可以通過 dbfilename 參數(shù)來指定 RDB 內(nèi)存快照文件名,默認(rèn)是 dbfilename dump.rdb。
rdb-del-sync-files
默認(rèn)配置是 rdb-del-sync-files no,主從進(jìn)行全量同步時(shí),通過傳輸 RDB 內(nèi)存快照文件實(shí)現(xiàn),沒有開啟 RDB 持久化的實(shí)例在同步完成后會(huì)刪除該文件,通常情況下保持默認(rèn)即可。
dir
我的工作目錄,注意這是目錄而不是文件, 默認(rèn)配置是dir ./。比如存放 RDB 內(nèi)存快照文件、AOF 文件。
1.3 主從復(fù)制
這部分配置很重要,涉及到主從復(fù)制的方方面面,是高可用的基石,重點(diǎn)對(duì)待啊伙計(jì)們。
replicaof
主從復(fù)制,使用replicaof <masterip> <masterport> 配置將當(dāng)前實(shí)例成為其他 Redis 服務(wù)的從節(jié)點(diǎn)。
- masterip,就是 master 的 IP。
- masterport,master 的端口。
有以下幾點(diǎn)需要注意。
- 我使用異步實(shí)現(xiàn)主從復(fù)制,當(dāng) Master 節(jié)點(diǎn)的 slave 節(jié)點(diǎn)數(shù)量小于指定的數(shù)量時(shí),你可以設(shè)置 Master 節(jié)點(diǎn)停止處理寫請(qǐng)求。
- 主從復(fù)制如果斷開的時(shí)間較短,slave 節(jié)點(diǎn)可以執(zhí)行部分重新同步,需要合理設(shè)置backlog size,保證這個(gè)緩存區(qū)能完整保存斷連期間 Master 接受寫請(qǐng)求的數(shù)據(jù),防止出現(xiàn)全量復(fù)制,具體配置后面會(huì)細(xì)說。
- 主從復(fù)制是自動(dòng)的,不需要用戶干預(yù)。
masterauth
如果當(dāng)前節(jié)點(diǎn)是 slave,且 master 節(jié)點(diǎn)配置了 requirepass 參數(shù)設(shè)置了密碼,那么 slave 節(jié)點(diǎn)必須使用該參數(shù)配置為 master 的密碼,否則 master 節(jié)點(diǎn)將拒絕該 slave 節(jié)點(diǎn)的請(qǐng)求。
配置方式為 masterauth <master-password>。
masteruser
在 6.0 以上版本,如果使用了我的 ACL 安全功能,只配置 masterauth 還不夠。因?yàn)槟J(rèn)用戶不能運(yùn)行 PSYNC 命令或者主從復(fù)制所需要的其他命令。
這時(shí)候,最好配置一個(gè)專門用于主從復(fù)制的特殊用戶,配置方式為 masteruser <username>。
replica-serve-stale-data
MySQL:“當(dāng) slave 節(jié)點(diǎn)與 master 失去連接,導(dǎo)致主從同步失敗的時(shí)候,還能處理客戶端請(qǐng)求么?”
slave 節(jié)點(diǎn)可以有以下兩種行為來決定是否處理客戶端請(qǐng)求。
- 配置為yes,slave 節(jié)點(diǎn)可以繼續(xù)處理客戶端請(qǐng)求,但是數(shù)據(jù)可能是舊的,因?yàn)樾碌臎]同步過來。也可能是空的,如果是第一次同步的話。
- 配置為no,slave 節(jié)點(diǎn)將返回錯(cuò)誤 MASTERDOWN Link with MASTER is down and replica-serve-stale-data is set to no給客戶端。但是以下的指令還是可以執(zhí)行:INFO, REPLICAOF, AUTH, SHUTDOWN, REPLCONF, ROLE, CONFIG, SUBSCRIBE,UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, COMMAND, POST,HOST and LATENCY。
我的默認(rèn)配置是 replica-serve-stale-data yes。
replica-read-only
這個(gè)配置用于控制 slave 實(shí)例能否接收寫指令,在 2.6 版本后默認(rèn)配置為 yes,表示 slave 節(jié)點(diǎn)只處理讀請(qǐng)求,如果為 no 則可讀可寫。
我建議保持默認(rèn)配置,讓 slave 節(jié)點(diǎn)只作為副本實(shí)現(xiàn)高可用。想要提高寫性能,使用集群模式橫向拓展更好。
repl-diskless-sync
主從復(fù)制過程中,新加入的 slave 節(jié)點(diǎn)和 slave 節(jié)點(diǎn)重連后無法進(jìn)行增量同步,需要進(jìn)行一次全量同步,master 節(jié)點(diǎn)會(huì)生成 RDB 內(nèi)存快照文件傳輸給 slave 節(jié)點(diǎn)。
所以這個(gè)配置是用于控制傳輸方式的,傳輸方式有兩種。
- Disk-backed(磁盤備份):master 節(jié)點(diǎn)創(chuàng)建新進(jìn)程將 RDB 內(nèi)存快照文件寫到磁盤,主進(jìn)程逐步將這個(gè)文件傳輸?shù)讲煌?slave 節(jié)點(diǎn)。
- Diskless(無盤備份):master 節(jié)點(diǎn)創(chuàng)建一個(gè)新進(jìn)程直接把 RDB 內(nèi)存快照內(nèi)容寫到 Socket,不會(huì)將 RDB 內(nèi)存快照文件持久化到磁盤。
使用磁盤備份的方式,master 保存在磁盤的 RDB 內(nèi)存快照文件可以讓多個(gè) slave 復(fù)用。
使用無盤備份的話,當(dāng) RDB 內(nèi)存快照文件傳輸開始,如果當(dāng)前有多個(gè)slave 節(jié)點(diǎn)與 master 建立連接,我會(huì)使用并行傳輸?shù)姆绞綄?RDB 內(nèi)容傳輸給多個(gè)節(jié)點(diǎn)。
默認(rèn)的配置是 repl-diskless-sync yes,表示使用無盤備份。在磁盤速度很慢,而網(wǎng)絡(luò)超快的情況下,無盤備份會(huì)更給力。如果網(wǎng)絡(luò)很慢,有可能會(huì)出現(xiàn)數(shù)據(jù)丟失,推薦你改成 no。
repl-diskless-sync-delay
使用無盤復(fù)制的話,如果此刻有新的 slave 發(fā)起全量同步,需要等待之前的傳輸完畢才能開啟傳輸。
所以可以使用配置 repl-diskless-sync-delay 5 參數(shù)指定一個(gè)延遲時(shí)間,這個(gè)單位是秒,讓 master 節(jié)點(diǎn)等待一會(huì),讓更多 slave 節(jié)點(diǎn)連接再執(zhí)行傳輸。
因?yàn)橐坏╅_始傳輸,master 節(jié)點(diǎn)無法響應(yīng)新的 slave 節(jié)點(diǎn)的全量復(fù)制請(qǐng)求,只能在隊(duì)列中等待下一次 RDB 內(nèi)存快照傳輸。
想要關(guān)閉這個(gè)功能,設(shè)置為 0 即可。
repl-diskless-load
mastar 節(jié)點(diǎn)有兩種方式傳輸 RDB,slave 節(jié)點(diǎn)也有兩種方式加載 master 傳輸過來的 RDB 數(shù)據(jù)。
- 傳統(tǒng)方式:接受到數(shù)據(jù)后,先持久化到磁盤,再從磁盤加載 RDB 文件恢復(fù)數(shù)據(jù)到內(nèi)存中,這是傳統(tǒng)方式。
- diskless-load:從 Socket 中一邊接受數(shù)據(jù),一邊解析,實(shí)現(xiàn)無盤化。
一共有三個(gè)取值可配置。
- disabled:不使用 diskless-load 方式,即采用磁盤化的傳統(tǒng)方式。
- on-empty-db:安全模式下使用 diskless-load(也就 slave 節(jié)點(diǎn)數(shù)據(jù)庫為空的時(shí)候使用 diskless-load)。
- swapdb:使用 diskless-load 方式加載,slave 節(jié)點(diǎn)會(huì)緩存一份當(dāng)前數(shù)據(jù)庫的數(shù)據(jù),再清空數(shù)據(jù)庫,接著進(jìn)行 Socket 讀取實(shí)現(xiàn)加載。緩存一份數(shù)據(jù)的目的是防止讀取 Socket 失敗。
需要注意的是,diskless-load 目前在實(shí)驗(yàn)階段,因?yàn)?RDB 內(nèi)存快照數(shù)據(jù)并沒有持久化到磁盤,因此有可能造成數(shù)據(jù)丟失;
另外,該模式會(huì)占用更多內(nèi)存,可能會(huì)導(dǎo)致 OOM。
repl-ping-replica-period
默認(rèn)配置repl-ping-replica-period 10 表示 slave 每 10 秒 PING 一次 master。
repl-timeout
很重要的一個(gè)參數(shù),slave 與 master 之間的復(fù)制超時(shí)時(shí)間,默認(rèn)配置是repl-timeout 60,表示在 60 秒內(nèi) ping 不通,則判定超時(shí)。
超時(shí)包含以下三種情況。
- slave 角度,全量同步期間,在 repl-timeout 時(shí)間內(nèi)沒有收到 master 傳輸?shù)?RDB 內(nèi)存快照文件。
- slave 角度,在 repl-timeout 時(shí)間內(nèi)沒有收到 master 發(fā)送的數(shù)據(jù)包或者 ping。
- master 角度,在 repl-timeout 時(shí)間內(nèi)沒有收到 REPCONF ACK (復(fù)制偏移量 offset)確認(rèn)信息。
當(dāng)檢測(cè)到超時(shí),將會(huì)關(guān)閉 master 與 slave 之間的連接,slave 會(huì)發(fā)起重新建立主從連接的請(qǐng)求,對(duì)于內(nèi)存數(shù)據(jù)比較大的系統(tǒng),可以增大 repl-timeout 的值。
你需要注意的是,這個(gè)配置一定要大于 repl-ping-replica-period的值,否則每次心跳監(jiān)測(cè)都超時(shí)。
repl-disable-tcp-nodelay
當(dāng) slave 與 master 全量同步(slave 發(fā)送 psync/sync 指令給 master)完成后,后續(xù)的增量同步是否設(shè)置成 TCP_NODELAY。
如果設(shè)置成 yes,master 將合并小的 TCP 包從而節(jié)省帶寬,但是會(huì)增加同步延遲(40 ms),造成 master 與 slave 數(shù)據(jù)不一致;設(shè)置成 no,則 master 會(huì)立即發(fā)送數(shù)據(jù)給 slave,沒有延遲。
默認(rèn)配置 repl-disable-tcp-nodelay no。
repl-backlog-size
設(shè)置主從復(fù)制積壓緩沖區(qū)(backlog) 容量大小,這是一個(gè)環(huán)形數(shù)組,正常主從同步不涉及到 repl-backlog。當(dāng)主從斷開重連,repl-backlog 的作用就出來了。
緩沖區(qū)用于存放斷連期間 master 接受的寫請(qǐng)求數(shù)據(jù),當(dāng)主從斷開重連,通常不需要執(zhí)行全量同步,只需要將斷連期間的部分?jǐn)?shù)據(jù)傳遞到 slave 即可。
主從復(fù)制積壓緩沖區(qū)越大,slave 可以承受的斷連時(shí)間越長(zhǎng)。
默認(rèn)配置是 repl-backlog-size 1mb,建議根據(jù)每秒流量大小和斷開重連時(shí)間長(zhǎng),設(shè)置大一點(diǎn),比如 128 mb。
repl-backlog-ttl
用于配置當(dāng) master 與 slave 斷連多少秒之后,master 清空主從復(fù)制積壓緩沖區(qū)(repl-backlog)。配置成 0 ,表示永遠(yuǎn)不清空。默認(rèn)配置repl-backlog-ttl 3600。
replica-priority
slave 優(yōu)先級(jí),這個(gè)配置是給哨兵使用的,當(dāng) master 節(jié)點(diǎn)掛掉,哨兵會(huì)選擇一個(gè) priority 最小的 slave 節(jié)點(diǎn)作為新的 master,這個(gè)值越小沒接越優(yōu)先選中。
如果是 0,那意味著這個(gè) slave 將不能選中成為 master,默認(rèn)配置是 replica-priority 100。
min-slaves-to-write 和 min-slaves-max-lag
這兩個(gè)配置要一起設(shè)置才有意義,如果有一個(gè)配置成 0,表示關(guān)閉該特性。
先看默認(rèn)配置含義。
如果 master 發(fā)現(xiàn)超過 3 個(gè) slave 節(jié)點(diǎn)連接 master 延遲大于 10 秒,那么 master 就停止接收客戶端寫請(qǐng)求。這么做的目的是為了盡可能保證主從數(shù)據(jù)一致性。
master 會(huì)記錄每個(gè) slave 最近一次發(fā)來 ping 的時(shí)間,掌握每個(gè) slave 的運(yùn)行情況。
tracking-table-max-keys
我在 Redis 6.0 版本,實(shí)現(xiàn)了服務(wù)端輔助實(shí)現(xiàn)客戶端緩存的特性,需要追蹤客戶端有哪些 key。當(dāng)某個(gè) key 被修改,我需要把這個(gè)失效信息發(fā)送到對(duì)應(yīng)的客戶端將本地緩存失效,這個(gè)配置就是用于指定追蹤表保存的最大 key 數(shù)量,一旦超過這個(gè)數(shù)量,即使這個(gè) key 沒有被修改,為了回收內(nèi)存我也會(huì)強(qiáng)制這個(gè) key 所在的客戶端緩存值失效。
設(shè)置 0 表示不限制,需要注意的是,如果使用廣播模式實(shí)現(xiàn)鍵追蹤,則不需要額外內(nèi)存,忽略這個(gè)配置。
使用廣播模式的不足就是與這個(gè) key 無關(guān)的客戶端也會(huì)收到失效消息。
1.4 安全
正是由于我快的一塌糊涂,攻擊者一秒鐘可以嘗試 100 萬個(gè)密碼,所以你應(yīng)該使用非常健壯的密碼。
ACL
ACL 日志的最大長(zhǎng)度,默認(rèn)配置 acllog-max-len 128 表示最大 128 mb。
另外,使用 aclfile /etc/redis/users.acl 配置 ACL 文件所在位置。
requirepass
當(dāng)前 Redis 服務(wù)器的訪問密碼,默認(rèn)是不需要密碼訪問,網(wǎng)絡(luò)危險(xiǎn),必須設(shè)置,如 requirepass magebyte660設(shè)置密碼為 “magebyte666”。
maxclients
設(shè)置客戶端同時(shí)連接的最大數(shù)量,默認(rèn)設(shè)置是 maxclients 10000。達(dá)到最大值,我將關(guān)閉客戶端新的連接,并發(fā)送一個(gè) max number of clients reached 錯(cuò)誤給客戶端。
1.5 內(nèi)存管理
作為用內(nèi)存保存數(shù)據(jù)的我,這部分的配置也相當(dāng)重要。
maxmemory
設(shè)置使用內(nèi)存最大字節(jié),當(dāng)內(nèi)存達(dá)到限制,我將嘗試根據(jù)配置的內(nèi)存淘汰策略(參見 maxmemory-policy)刪除一些 key。建議你不要設(shè)置太大的內(nèi)存,防止執(zhí)行 RDB 內(nèi)存快照文件或者 AOF 重寫的時(shí)候因數(shù)據(jù)太大而阻塞過長(zhǎng)時(shí)間。
推薦最大設(shè)置為 maxmemory 6GB。
如果淘汰策略是 noeviction,當(dāng)收到寫請(qǐng)求,我將回復(fù)錯(cuò)誤給客戶端,讀請(qǐng)求依然可以執(zhí)行。
如果你把我當(dāng)做一個(gè) LRU 或 LFU 緩存系統(tǒng)的時(shí)候,那請(qǐng)用心關(guān)注以下配置。
maxmemory-policy
設(shè)置內(nèi)存淘汰策略,定義當(dāng)內(nèi)存滿時(shí)如何淘汰 key,默認(rèn)配置是 noeviction。
- volatile-lru -> 在設(shè)置過期時(shí)間的 key 中使用近似 LRU 驅(qū)逐。
- allkeys-lru -> 在所有 key 中使用近似 LRU 驅(qū)逐。
- volatile-lfu -> 在過期 key 中使用近似 LFU 驅(qū)逐。
- allkeys-lfu -> 在所有 key 中使用近似 LFU。
- volatile-random -> 在設(shè)置了過期時(shí)間的 key 中隨機(jī)刪除一個(gè)。
- allkeys-random -> 在所有的 key 中隨機(jī)刪除一個(gè)。
- volatile-ttl -> 誰快過期就刪誰。
- noeviction -> 不刪除任何 key,內(nèi)存滿了直接返回報(bào)錯(cuò)。
maxmemory-samples
LRU, LFU and minimal TTL algorithms 不是精確的算法,是一個(gè)近似的算法(主要為了節(jié)省內(nèi)存)。
所以需要你自己權(quán)衡速度和精確度。默認(rèn)會(huì)抽取 5 個(gè) key,選擇一個(gè)最近最少使用的 key 淘汰,你可以改變這個(gè)數(shù)量。
默認(rèn)的 5 可以提供不錯(cuò)的結(jié)果。配置 10 會(huì)非常接近真實(shí)的 LRU 但是會(huì)耗費(fèi)更多的 CPU,配置 3 會(huì)更快,但是就不那么精確了。
replica-ignore-maxmemory
從 Redis 5.0 開始,默認(rèn)情況下 slave 節(jié)點(diǎn)會(huì)忽略 maxmemory 配置,除非在故障轉(zhuǎn)移后或手動(dòng)將其提升為 master。這意味著只有 master 才會(huì)執(zhí)行內(nèi)存淘汰策略,當(dāng) master 刪除 key 后會(huì)發(fā)送 DEL指令給 slave。
默認(rèn)配置replica-ignore-maxmemory yes。
active-expire-effort
我有兩種方式刪除過期數(shù)據(jù)。
- 后臺(tái)周期性選取部分?jǐn)?shù)據(jù)刪除。
- 惰性刪除,當(dāng)訪問請(qǐng)求到某個(gè) key 的時(shí)候,發(fā)現(xiàn)該 key 已經(jīng)過期則刪除。
這個(gè)配置用于指定過期 key 滯留在內(nèi)存中的比例,默認(rèn)值是 1,表示最多只能有 10 % 的過期 key 駐留在內(nèi)存中,值設(shè)置的越小,那么一次淘汰周期內(nèi)需需要消耗的 CPU 將會(huì)更多,因?yàn)樾枰獎(jiǎng)h除更多的過期數(shù)據(jù)。
1.6 惰性釋放
MySQL:“ 可以使用非阻塞的方式刪除 bigkey 么?”
我提供了兩種刪除 key 的基本命令用于刪除數(shù)據(jù)。
- DEL? 指令:這是一個(gè)阻塞的刪除,執(zhí)行該指令會(huì)停止處理寫請(qǐng)求,使用同步的方式去回收 DEL 刪除的對(duì)象的內(nèi)存。如果這個(gè) key 對(duì)應(yīng)的 value 是一個(gè)非常小的對(duì)象, DEL 執(zhí)行的時(shí)間非常短,時(shí)間復(fù)雜度為 O(1) 或者 O(log n)。如果 key 對(duì)應(yīng)的 value 非常大,比如集合對(duì)象的數(shù)據(jù)包含百萬個(gè)元素,服務(wù)器將阻塞很長(zhǎng)時(shí)間(幾秒鐘)才能完成操作。
- UNLINK(非阻塞刪除)、(異步刪除) FLUSHALL ASYNC/FLUSHDB ASYNC:后臺(tái)回收內(nèi)存,這些指令在常量級(jí)別時(shí)間內(nèi)執(zhí)行,會(huì)使用一個(gè)新的線程在后臺(tái)漸進(jìn)的刪除并釋放內(nèi)存(Lazy Free 機(jī)制)。
lazyfree-lazy-eviction
由于 maxmemory 和 maxmemory-policy 策略配置,我會(huì)刪除一些數(shù)據(jù),防止內(nèi)存爆掉。使用lazyfree-lazy-eviction yes表示使用 lazy free 機(jī)制,該場(chǎng)景開啟 lazy free 可能會(huì)導(dǎo)致淘汰數(shù)據(jù)的內(nèi)存釋放不及時(shí),出現(xiàn)內(nèi)存超限。
lazyfree-lazy-expire
對(duì)于設(shè)置了 TTL 的鍵,過期后刪除。如果想啟用 lazy free 機(jī)制刪除,則配置 lazyfree-lazy-eviction yes。
lazyfree-lazy-server-del
針對(duì)有些指令在處理已存在的鍵時(shí),會(huì)帶有一個(gè)隱式的 DEL 鍵的操作。
如 rename 命令,當(dāng)目標(biāo)鍵已存在,我會(huì)先刪除目標(biāo)鍵,如果這些目標(biāo)鍵是一個(gè) big key,那可能會(huì)出現(xiàn)阻塞刪除的性能問題。此參數(shù)設(shè)置就是解決這類問題,建議配置 lazyfree-lazy-server-del yes 開啟。
replica-lazy-flush
該配置針對(duì) slave 進(jìn)行全量數(shù)據(jù)同步,在加載 master 的 RDB 內(nèi)存快照文件之前,會(huì)先運(yùn)行 flashall清理數(shù)據(jù)的時(shí)候是否采用異步 flush 機(jī)制。
推薦你使用 replica-lazy-flush yes配置,可減少全量同步耗時(shí),從而減少 master 因輸出緩沖區(qū)暴漲引起的內(nèi)存增長(zhǎng)。
lazyfree-lazy-user-del
意思是是否將 DEL 指令的默認(rèn)行為替換成 lazy free 機(jī)制刪除,效果就跟 UNLINK 一樣,只要配置成 lazyfree-lazy-user-del yes。
lazyfree-lazy-user-flush
FLUSHDB, FLUSHALL, SCRIPT FLUSH, FUNCTION FLUSH可以使用額外參數(shù) ASYNC|SYNC 決定使用同步還是異步操作,當(dāng)沒有指定這個(gè)可選項(xiàng),可以通過 lazyfree-lazy-user-flush yes 表示使用異步刪除。
IO 多線程
大家知道我是單線程模型處理讀寫請(qǐng)求,但是有一些操作可以使用其他線程處理,比如 UNLINK,I/O 讀寫操作。
在 6.0 版本,我提供了 I/O 多線程處理 Socket 讀寫,利用 I/O 多線程可以提高客戶端 Socket 讀寫性能。
默認(rèn)配置是關(guān)閉的,我只建議當(dāng)你的機(jī)器至少是 4 核 CPU 或者更多的情況啟用,并且配置的線程數(shù)少于機(jī)器總 CPU 核數(shù),配置超過 8 個(gè)線程對(duì)提升沒什么幫助。
當(dāng)你的機(jī)器是四核 CPU,那可以嘗試配置使用 2~3 個(gè) I/O 線程,如果是 8 核 CPU,一般只需要配置 6 個(gè)線程。
如下配置表示開啟 I/O 線程組,線程組的 I/O 線程數(shù)量為 3。
1.7 AOF 持久化
除了 RDB 內(nèi)存快照文件作為持久化手段以外,還能使用 AOF(Append only file) 實(shí)現(xiàn)持久化,AOF 是一種可選的持久化策略提供更好數(shù)據(jù)安全性。
默認(rèn)配置下,我最多只會(huì)丟失一秒的數(shù)據(jù),你甚至可以配置更高級(jí)別,最多只丟失一次 write 操作,但這樣會(huì)對(duì)損耗性能。
appendonly
appendonly yes 表示開啟 AOF 持久化,可以同時(shí)開啟 AOF 和 RDB 內(nèi)存快照持久化,如果開啟了 AOF ,我會(huì)先加載 AOF 用于恢復(fù)內(nèi)存數(shù)據(jù)。
appendfilename
指定 AOF 文件名稱,默認(rèn)名字是 appendonly.aof。為了方便,你可以配置 appenddirname 指定 AOF 文件存儲(chǔ)目錄。
appendfsync
調(diào)用操作系統(tǒng)的 fsync()函數(shù)告訴操作系統(tǒng)把輸出緩沖區(qū)的數(shù)據(jù)持久化到磁盤, AOF 文件刷寫的頻率有三種。
- no:不去主動(dòng)調(diào)用 fsync(),讓操作系統(tǒng)自己決定何時(shí)寫磁盤。
- always:每次 write 操作之后都調(diào)用 fsync(),非常慢,但是數(shù)據(jù)安全性最高。
- everysec:每秒調(diào)用一次 fsync(),一個(gè)折中的策略,最多丟失一秒的數(shù)據(jù)。
默認(rèn)配置是 appendfsync everysec,推薦大家這么設(shè)置,兼顧了速度和數(shù)據(jù)安全。
no-appendfsync-on-rewrite
當(dāng) appendfsync 的配置設(shè)置成 always或者 everysec ,現(xiàn)在有一個(gè)后臺(tái) save 進(jìn)程(可能是生成 RDB 內(nèi)存快照的 bgsave 進(jìn)程,也有可能是 AOF rewrite 進(jìn)程)正在進(jìn)行大量的磁盤 I/O 操作,會(huì)造成調(diào)用 fsync()執(zhí)行太長(zhǎng),后續(xù)其他想要調(diào)用 fsync() 的進(jìn)程就會(huì)阻塞。
為了緩解這個(gè)問題,可以使用以下配置 no-appendfsync-on-rewrite yes 表示當(dāng)已經(jīng)有 bgsave和bgrewriteaof 后臺(tái)進(jìn)程在調(diào)用 fsync() 時(shí),不再開啟新進(jìn)程執(zhí)行 AOF 文件寫入。
這樣的話,就會(huì)出現(xiàn)當(dāng)前有子進(jìn)程在做 bgsave 或者其他的磁盤操作時(shí),我就無法繼續(xù)寫 AOF 文件,這意味著可能會(huì)丟失更多數(shù)據(jù)。
如果有延遲問題,請(qǐng)將此選項(xiàng)改為 yes。否則將其保留為 no。從持久化的角度來看,no是最安全的選擇。
AOF 重寫
為了防止 AOF 文件過大,antirez 大佬給我搞了個(gè) AOF 重寫機(jī)制。
auto-aof-rewrite-percentage 100 表示當(dāng)前 AOF 文件大小超過上一次重寫的 AOF 文件大小的百分之多少(如果沒有執(zhí)行過 AOF 重寫,那就參照原始 AOF 文件大?。瑒t執(zhí)行 AOF 文件重寫操作。
除了這個(gè)配置,你還要配置 auto-aof-rewrite-min-size 64mb 用于指定觸發(fā) AOF 重寫操作的文件大小。
如果該 AOF 文件大小小于該值,即使文件增長(zhǎng)比例達(dá)到 100%,我也不會(huì)觸發(fā) AOF 重寫操作,這是為了防止 AOF 文件其實(shí)很小,但是滿足增長(zhǎng)百分比時(shí)的多余 AOF 重寫操作。
如果配置為auto-aof-rewrite-percentage 0 ,表示禁用 AOF 重寫功能,建議大家開啟 AOF 重寫,防止文件過大。
aof-load-truncated
MySQL:如果 AOF 文件是損壞的,你還加載數(shù)據(jù)還原到內(nèi)存中么?
加載 AOF 文件把數(shù)據(jù)還原到內(nèi)存中,文件可能是損壞的,比如文件末尾是錯(cuò)誤的。這種情況一般是由于宕機(jī)導(dǎo)致,尤其是使用 ext4 文件系統(tǒng)掛載時(shí)沒配置 data=ordered 選項(xiàng)。
在這種情況下,我可以直接報(bào)錯(cuò),或者盡可能的讀取可讀的 AOF 內(nèi)容。
如果配置成 aof-load-truncated yes,我依然會(huì)加載并讀取這個(gè)損壞的 AOF 文件,并記錄一個(gè)錯(cuò)誤日志通知程序員。
配置成 aof-load-truncated no,我就會(huì)報(bào)錯(cuò)并拒絕啟動(dòng)服務(wù),你需要使用 redis-check-aof 工具修復(fù) AOF 文件,再啟動(dòng) Redis。如果修復(fù)后還是錯(cuò)誤,我依然報(bào)錯(cuò)并拒絕啟動(dòng)。
aof-use-rdb-preamble
這就是大名鼎鼎的 RDB-AOF 混合持久化功能,配置成 aof-use-rdb-preamble yes(必須先開啟 AOF),AOF 重寫生成的文件將同時(shí)包含 RDB 格式的內(nèi)容和 AOF 格式內(nèi)容。
混合持久化是在 AOF 重寫完成的,開啟混合持久化后,fork 出的子進(jìn)程先將內(nèi)存數(shù)據(jù)以 RDB 的方式寫入 AOF 文件,接著把 RDB 格式數(shù)據(jù)寫入 AOF 文件期間收到的增量命令從重寫緩沖區(qū)以 AOF 格式寫到文件中。
寫入完成后通知主進(jìn)程更新統(tǒng)計(jì)信息,并把含有 RDB 格式和 AOF 格式的 AOF 文件替換舊的 AOF 文件。
這樣的好處是可以結(jié)合 RDB 和 AOF 的優(yōu)點(diǎn),實(shí)現(xiàn)快速加載同時(shí)避免丟失過多數(shù)據(jù),缺點(diǎn)是 AOF 文件的 RDB 部分內(nèi)容不是 AOF 格式,可讀性差(都是程序解析讀取,哪個(gè)傻瓜程序員去讀這個(gè)呀),強(qiáng)烈推薦你使用這個(gè)來保證持久化。
aof-timestamp-enabled
我在 7.0 版本新增的特性,大體就是講 AOF 現(xiàn)在支持時(shí)間戳了,你可以做到基于時(shí)間點(diǎn)來恢復(fù)數(shù)據(jù)。
默認(rèn)是是 aof-timestamp-enabled no 表示關(guān)閉該特性,你可以按照實(shí)際需求選擇開啟。
1.7 Cluster 集群
Redis Cluster 集群相關(guān)配置,使用集群方式的你必須重視和知曉。別嘴上原理說的頭頭是道,而集群有哪些配置?如何配置讓集群快到飛起,實(shí)現(xiàn)真正的高可用卻一頭霧水,通過下面這些配置詳解也讓你對(duì)集群原理更加深刻。
cluster-enabled
普通的 Redis 實(shí)例是不能成為集群的一員,想要將該節(jié)點(diǎn)加入 Redis Cluster,需要設(shè)置 cluster-enabled yes。
cluster-config-file
cluster-config-file nodes-6379.conf 指定集群中的每個(gè)節(jié)點(diǎn)文件。
集群中的每個(gè)節(jié)點(diǎn)都有一個(gè)配置文件,這個(gè)文件并不是讓程序員編輯的,是我自己創(chuàng)建和更新的,每個(gè)節(jié)點(diǎn)都要使用不同的配置文件,一定要確保同一個(gè)集群中的不同節(jié)點(diǎn)使用的是不同的文件。
cluster-node-timeout
設(shè)置集群節(jié)點(diǎn)不可用的最大超時(shí)時(shí)間,節(jié)點(diǎn)失效檢測(cè)。集群中當(dāng)一個(gè)節(jié)點(diǎn)向另一個(gè)節(jié)點(diǎn)發(fā)送 PING 命令,但是目標(biāo)節(jié)點(diǎn)未在給定的時(shí)限內(nèi)返回 PING 命令的回復(fù)時(shí),那么發(fā)送命令的節(jié)點(diǎn)會(huì)將目標(biāo)節(jié)點(diǎn)標(biāo)記為 PFAIL(possible failuer,可能已失效);
如果 master 節(jié)點(diǎn)超過這個(gè)時(shí)間還是無響應(yīng),則用它的從節(jié)點(diǎn)將啟動(dòng)故障遷移,升級(jí)成主節(jié)點(diǎn)。
默認(rèn)配置是 cluster-node-timeout 15000,單位是毫秒數(shù)。
cluster-port
該端口是集群總線監(jiān)聽 TCP 連接的端口,默認(rèn)配置為 cluster-port 0,我就會(huì)把端口綁定為客戶端命令端口 + 10000(客戶端端口默認(rèn) 6379,所以綁定為 16379 作為集群總線端口)。每個(gè) Redis Cluster 節(jié)點(diǎn)都需要開放兩個(gè)端口:
- 一個(gè)用于服務(wù)于客戶端的 TCP 端口,比如 6379.
- 另一個(gè)稱為集群總線端口,節(jié)點(diǎn)使用集群總線進(jìn)行故障監(jiān)測(cè)、配置更新、故障轉(zhuǎn)移等??蛻舳瞬灰c集群總線端口通信,另外請(qǐng)確保在防火墻打開這兩個(gè)端口,否則 Redis 集群之間將無法通信。
cluster-replica-validity-factor
該配置用于決定當(dāng) Redis Cluster 集群中,一個(gè) master 宕機(jī)后,如何選擇一個(gè) slave 節(jié)點(diǎn)完成故障轉(zhuǎn)移自動(dòng)恢復(fù)(failover)。如果設(shè)置為 0 ,則不管 slave 與 master 之間斷開多久,都有資格成為 master。
下面提供了兩種方式來評(píng)估 slave 的數(shù)據(jù)是否太舊。
- 如果有多個(gè) slave 可以 failover,他們之間會(huì)通過交換信息選出擁有擁有最大復(fù)制 offset 的 slave 節(jié)點(diǎn)。
- 每個(gè) slave 節(jié)點(diǎn)計(jì)算上次與 master 節(jié)點(diǎn)交互的時(shí)間,這個(gè)交互包含最后一次ping 操作、master 節(jié)點(diǎn)傳輸過來的寫指令、上次與 master 斷開的時(shí)間等。如果上次交互的時(shí)間過去很久,那么這個(gè)節(jié)點(diǎn)就不會(huì)發(fā)起 failover。
針對(duì)第二點(diǎn),交互時(shí)間可以通過配置定義,如果 slave 與 master 上次交互的時(shí)間大于 (node-timeout * cluster-replica-validity-factor) + repl-ping-replica-period,該 slave 就不會(huì)發(fā)生 failover。
例如,``node-timeout = 30秒,cluster-replica-validity-factor=10,repl-ping-slave-period=10`秒, 表示 slave 節(jié)點(diǎn)與 master 節(jié)點(diǎn)上次交互時(shí)間已經(jīng)過去了 310 秒,那么 slave 節(jié)點(diǎn)就不會(huì)做 failover。
調(diào)大 cluster-replica-validity-factor 則允許存儲(chǔ)過舊數(shù)據(jù)的 slave 節(jié)點(diǎn)提升為 master,調(diào)小的話可能會(huì)導(dǎo)致沒有 slave 節(jié)點(diǎn)可以升為 master 節(jié)點(diǎn)。
考慮高可用,建議大家設(shè)置為 cluster-replica-validity-factor 0。
cluster-migration-barrier
沒有 slave 節(jié)點(diǎn)的 master 節(jié)點(diǎn)稱為孤兒 master 節(jié)點(diǎn),這個(gè)配置就是用于防止出現(xiàn)孤兒 master。
當(dāng)某個(gè) master 的 slave 節(jié)點(diǎn)宕機(jī)后,集群會(huì)從其他 master 中選出一個(gè)富余的 slave 節(jié)點(diǎn)遷移過來,確保每個(gè) master 節(jié)點(diǎn)至少有一個(gè) slave 節(jié)點(diǎn),防止當(dāng)孤立 master 節(jié)點(diǎn)宕機(jī)時(shí),沒有 slave 節(jié)點(diǎn)可以升為 master 導(dǎo)致集群不可用。
默認(rèn)配置為 cluster-migration-barrier 1,是一個(gè)遷移臨界值。
含義是:被遷移的 master 節(jié)點(diǎn)至少還有 1 個(gè) slave 節(jié)點(diǎn)才能做遷移操作。比如 master A 節(jié)點(diǎn)有 2 個(gè)以上 slave 節(jié)點(diǎn) ,當(dāng)集群出現(xiàn)孤兒 master B 節(jié)點(diǎn)時(shí),A 節(jié)點(diǎn)富余的 slave 節(jié)點(diǎn)可以遷移到 master B 節(jié)點(diǎn)上。
生產(chǎn)環(huán)境建議維持默認(rèn)值,最大可能保證高可用,設(shè)置為非常大的值或者配置 cluster-allow-replica-migration no 禁用自動(dòng)遷移功能。
cluster-allow-replica-migration 默認(rèn)配置為 yes,表示允許自動(dòng)遷移。
cluster-require-full-coverage
默認(rèn)配置是 yes,表示為當(dāng) redis cluster 發(fā)現(xiàn)還有哈希槽沒有被分配時(shí)禁止查詢操作。
這就會(huì)導(dǎo)致集群部分宕機(jī),整個(gè)集群就不可用了,當(dāng)所有哈希槽都有分配,集群會(huì)自動(dòng)變?yōu)榭捎脿顟B(tài)。
如果你希望 cluster 的子集依然可用,配置成 cluster-require-full-coverage no。
cluster-replica-no-failover
當(dāng)配置成 yes,在 master 宕機(jī)時(shí),slave 不會(huì)做故障轉(zhuǎn)移升為 master。
這個(gè)配置在多數(shù)據(jù)中心的情況下會(huì)很有用,你可能希望某個(gè)數(shù)據(jù)中心永遠(yuǎn)不要升級(jí)為 master 節(jié)點(diǎn),否則 master 節(jié)點(diǎn)就漂移到其他數(shù)據(jù)中心了,正常情況設(shè)置成 no。
cluster-allow-reads-when-down
默認(rèn)是 no,表示當(dāng)集群因主節(jié)點(diǎn)數(shù)量達(dá)不到最小值或者哈希槽沒有完全分配而被標(biāo)記為失效時(shí),節(jié)點(diǎn)將停止所有客戶端請(qǐng)求。
設(shè)置成 yes,則允許集群失效的情況下依然可從節(jié)點(diǎn)中讀取數(shù)據(jù),保證了高可用。
cluster-allow-pubsubshard-when-down
配置成 yes,表示當(dāng)集群因主節(jié)點(diǎn)數(shù)量達(dá)不到最小值或者哈希槽沒有完全分配而被標(biāo)記為失效時(shí),pub/sub 依然可以正常運(yùn)行。
cluster-link-sendbuf-limit
設(shè)置每個(gè)集群總線連接的發(fā)送字節(jié)緩沖區(qū)的內(nèi)存使用限制,超過限制緩沖區(qū)將被清空(主要為了防止發(fā)送緩沖區(qū)發(fā)送給慢速連接時(shí)無限延長(zhǎng)時(shí)間的問題)。
默認(rèn)禁用,建議最小設(shè)置 1gb,這樣默認(rèn)情況下集群連接緩沖區(qū)可以容納至少一條 pubsub 消息(client-query-buffer-limit 默認(rèn)是 1gb);
1.8 性能監(jiān)控
慢查詢?nèi)罩?/h3>
慢查詢(Slow Log)日志是我用于記錄慢查詢執(zhí)行時(shí)間的日志系統(tǒng),只要查詢超過配置的時(shí)間,都會(huì)記錄。slowlog 只保存在內(nèi)存中,因此效率很高,大家不用擔(dān)心會(huì)影響到 Redis 的性能。
執(zhí)行時(shí)間不包括 I/O 操作的時(shí)間,比如與客戶端建立連接、發(fā)送回復(fù)等,只記錄執(zhí)行命令執(zhí)行階段所需要的時(shí)間。
你可以使用兩個(gè)參數(shù)配置慢查詢?nèi)罩鞠到y(tǒng)。
- slowlog-log-slower-than:指定對(duì)執(zhí)行時(shí)間大于多少微秒(microsecond,1 秒 = 1,000,000 微秒)的查詢進(jìn)行記錄,默認(rèn)是 10000 微妙,推薦你先執(zhí)行基線測(cè)試得到一個(gè)基準(zhǔn)時(shí)間,通常這個(gè)值可以設(shè)置為基線性能最大延遲的 3 倍。
- slowlog-max-len:設(shè)定最多保存多少條慢查詢的日志,slowlog 本身是一個(gè) FIFO 隊(duì)列,當(dāng)超過設(shè)定的最大值后,我會(huì)把最舊的一條日志刪除。默認(rèn)配置 128,如果設(shè)置太大會(huì)占用多大內(nèi)存。
延遲監(jiān)控
延遲監(jiān)控(LATENCY MONITOR)系統(tǒng)會(huì)在運(yùn)行時(shí)抽樣部分命令來幫助你分析 Redis 卡頓的原因。
通過 LATENCY命令,可以打印一些視圖和報(bào)告,系統(tǒng)只會(huì)記錄大于等于指定值的命令。
默認(rèn)配置 latency-monitor-threshold 0,設(shè)置 0 表示關(guān)閉這個(gè)功能。沒有延遲問題,沒必要開啟開啟監(jiān)控,因?yàn)闀?huì)對(duì)性能造成很大影響。
在運(yùn)行過程中你懷疑有延遲性能問題,想要監(jiān)控的話可以使用 CONFIG SET latency-monitor-threshold <milliseconds>開啟,單位是毫秒。
1.9 高級(jí)設(shè)置
這部分配置主要圍繞以下幾個(gè)方面。
- 指定不同數(shù)據(jù)類型根據(jù)不同條數(shù)下使用不同的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ),合理配置能做到更快和更省內(nèi)存。
- 客戶端緩沖區(qū)相關(guān)配置。
- 漸進(jìn)式 rehash 資源控制。
- LFU 調(diào)優(yōu)。
- RDB 內(nèi)存快照文件、AOF 文件同步策略。
Hashes(散列表)
在 Redis 7.0 版本散列表數(shù)據(jù)類型有兩種數(shù)據(jù)結(jié)構(gòu)保存數(shù)據(jù),分別為散列表和 listpack。當(dāng)數(shù)據(jù)量很小時(shí),可以使用更高效的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ),從而達(dá)到在不影響性能的情況下節(jié)省內(nèi)存。
- hash-max-listpack-entries 512:指定使用 listpack 存儲(chǔ)的最大條目數(shù)。
- hash-max-listpack-value 64:listpack 中,條目 value 值最大字節(jié)數(shù),建議設(shè)置成 1024。
在 7.0 版本以前,使用的是 ziplist 數(shù)據(jù)結(jié)構(gòu),配置如下。
Lists(列表)
Lists 也可以使用一種特殊方式進(jìn)行編碼來節(jié)省大量?jī)?nèi)存空間。在 Redis 7.0 之后,Lits 底層的數(shù)據(jù)結(jié)構(gòu)使用 linkedlist 或者 listpack 。
Redis 3.2 版本,List 內(nèi)部是通過 linkedlist 和 quicklist 實(shí)現(xiàn),quicklist 是一個(gè)雙向鏈表, quicklist 的每個(gè)節(jié)點(diǎn)都是一個(gè) ziplist,從而實(shí)現(xiàn)節(jié)省內(nèi)存。
元素少時(shí)用 quicklist,元素多時(shí)用 linkedlist。listpack 的目的就是用于替代 ziplist 和 quicklist。listpack 也叫緊湊列表,它的特點(diǎn)就是用一塊連續(xù)的內(nèi)存空間來緊湊地保存數(shù)據(jù),同時(shí)為了節(jié)省內(nèi)存空間
list-max-ziplist-size
7.0 版本之前l(fā)ist-max-ziplist-size 用于配置 quicklist 中的每個(gè)節(jié)點(diǎn)的 ziplist 的大小。當(dāng)這個(gè)值配置為正數(shù)時(shí)表示 quicklist 每個(gè)節(jié)點(diǎn)的 ziplist 最多可存儲(chǔ)元素?cái)?shù)量,超過該值就會(huì)使用 linkedlist 存儲(chǔ)。
當(dāng) list-max-ziplist-size 為負(fù)數(shù)時(shí)表示限制每個(gè) quicklistNode 的 ziplist 的內(nèi)存大小,超過這個(gè)大小就會(huì)使用 linkedlist 存儲(chǔ)數(shù)據(jù),每個(gè)值有以下含義:
- -5:每個(gè) quicklist 節(jié)點(diǎn)上的 ziplist 大小最大 64 kb <--- 正常環(huán)境不推薦
- -4:每個(gè) quicklist 節(jié)點(diǎn)上的 ziplist 大小最大 32 kb <--- 不推薦
- -3:每個(gè) quicklist 節(jié)點(diǎn)上的 ziplist 大小最大 16 kb <--- 可能不推薦
- -2:每個(gè) quicklist 節(jié)點(diǎn)上的 ziplist 大小最大 8 kb <--- 不錯(cuò)
- -1:每個(gè) quicklist 節(jié)點(diǎn)上的 ziplist 大小最大 4kb <--- 不錯(cuò)
默認(rèn)值為 -2,也是官方最推薦的值,當(dāng)然你可以根據(jù)自己的實(shí)際情況進(jìn)行修改。
list-max-listpack-size
7.0 之后,配置修改為list-max-listpack-size -2則表示限制每個(gè) listpack 大小,不再贅述。
list-compress-depth
壓縮深度配置,用來配置壓縮 Lists 的,當(dāng) Lists 底層使用 linkedlist 也是可以壓縮的,默認(rèn)是 list-compress-depth 0表示不壓縮。一般情況下,Lists 的兩端訪問的頻率高一些,所以你可以考慮把中間的數(shù)據(jù)進(jìn)行壓縮。
不同參數(shù)值的含義如下。
- 0,關(guān)閉壓縮,默認(rèn)值。
- 1,兩端各有一個(gè)節(jié)點(diǎn)不壓縮。
- 2,兩端各有兩個(gè)節(jié)點(diǎn)不壓縮。
- N,依次類推,兩端各有 N 個(gè)節(jié)點(diǎn)不壓縮。
需要注意的是,head 和 tail 節(jié)點(diǎn)永遠(yuǎn)都不會(huì)被壓縮。
Sets(無序集合)
Sets 底層的數(shù)據(jù)結(jié)構(gòu)可以是 intset(整形數(shù)組)和 Hashtable(散列表),intset 你可以理解成數(shù)組,Hashtable 就是普通的散列表(key 存的是 Sets 的值,value 為 null)。有沒有覺得 Sets 使用散列表存儲(chǔ)是意想不到的事情?
set-max-intset-entries
當(dāng)集合的元素都是 64 位以內(nèi)的十進(jìn)制整數(shù)時(shí)且長(zhǎng)度不超過 set-max-intset-entries 配置的值(默認(rèn) 512),Sets 的底層會(huì)使用 intset 存儲(chǔ)節(jié)省內(nèi)存。添加的元素大于 set-max-intset-entries配置的值,底層實(shí)現(xiàn)由 intset 轉(zhuǎn)成散列表存儲(chǔ)。
SortedSets(有序集合)
在 Redis 7.0 版本之前,有序集合底層的數(shù)據(jù)結(jié)構(gòu)有 ziplist 和 skipist,之后使用 listpack 代替了 ziplist。
7.0 版本之前,當(dāng)集合元素個(gè)數(shù)小于 zset-max-ziplist-entries配置,同時(shí)且每個(gè)元素的值大小都小于zset-max-ziplist-value配置(默認(rèn) 64 字節(jié),推薦調(diào)大到 128)時(shí),我將使用 ziplist 數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)數(shù)據(jù),有效減少內(nèi)存使用。與此類似,7.0 版本之后我將使用 listpack 存儲(chǔ)。
HyperLogLog
HyperLogLog 是一種高級(jí)數(shù)據(jù)結(jié)構(gòu),統(tǒng)計(jì)基數(shù)的利器。HyperLogLog 的存儲(chǔ)結(jié)構(gòu)分為密集存儲(chǔ)結(jié)構(gòu)和稀疏存儲(chǔ)結(jié)構(gòu)兩種,默認(rèn)為稀疏存儲(chǔ)結(jié)構(gòu),而我們常說的占用 12K 內(nèi)存的則是密集存儲(chǔ)結(jié)構(gòu),稀疏結(jié)構(gòu)占用的內(nèi)存會(huì)更小。
hll-sparse-max-bytes
默認(rèn)配置是 hll-sparse-max-bytes 3000,單位是 Byte,這個(gè)配置用于決定存儲(chǔ)數(shù)據(jù)使用稀疏數(shù)據(jù)結(jié)構(gòu)(sparse)還是稠密數(shù)據(jù)結(jié)構(gòu)(dense)。
如果 HyperLogLog 存儲(chǔ)內(nèi)容大小大于 hll-sparse-max-bytes 配置的值將會(huì)轉(zhuǎn)換成稠密的數(shù)據(jù)結(jié)構(gòu)(dense)。
推薦的值是 0~3000,這樣PFADD命令的并不會(huì)慢多少,還能節(jié)省空間。如果內(nèi)存空間相對(duì) cpu 資源更缺乏,可以將這個(gè)值提升到 10000。
Streams(流)
Stream 是 Redis 5.0 版本新增的數(shù)據(jù)類型。Redis Streams 是一些由基數(shù)樹(Radix Tree)連接在一起的節(jié)點(diǎn)經(jīng)過 delta 壓縮后構(gòu)成的,這些節(jié)點(diǎn)與 Stream 中的消息條目(Stream Entry)并非一一對(duì)應(yīng),而是每個(gè)節(jié)點(diǎn)中都存儲(chǔ)著若干 Stream 條目,因此這些節(jié)點(diǎn)也被稱為宏節(jié)點(diǎn)或大節(jié)點(diǎn)。
stream-node-max-bytes 4096
單位為 Byte,默認(rèn)值 4096,用于設(shè)定每個(gè)宏節(jié)點(diǎn)占用的內(nèi)存上限為 4096,0 表示無限制。
stream-node-max-entries 100
用于設(shè)定每個(gè)宏節(jié)點(diǎn)存儲(chǔ)元素個(gè)數(shù)。默認(rèn)值 100,0 表示無限制。當(dāng)一個(gè)宏節(jié)點(diǎn)存儲(chǔ)的 Stream 條目到達(dá)上限,新添加的條目會(huì)存儲(chǔ)到新的宏節(jié)點(diǎn)中。
rehash
我采用的是漸進(jìn)式 rehash,這是一個(gè)惰性策略,不會(huì)一次性把所有數(shù)據(jù)遷移完,而是分散到每次請(qǐng)求中,這樣做的目的是防止數(shù)據(jù)太多要遷移阻塞主線程。
在漸進(jìn)式 rehash 的同時(shí),推薦你使用 activerehashing yes開啟定時(shí)輔助執(zhí)行 rehash,默認(rèn)情況下每一秒執(zhí)行 10 次 rehash 加快遷移速度,盡可能釋放內(nèi)存。
關(guān)閉該功能的話,如果這些 key 不再活躍不被被訪問到,rehash 操作可能不再有機(jī)會(huì)完成,會(huì)導(dǎo)致散列表占用更多內(nèi)存。
客戶端輸出緩沖區(qū)限制
這三個(gè)配置是用來強(qiáng)制斷開客戶端連接的,當(dāng)客戶端沒有及時(shí)把緩沖區(qū)的數(shù)據(jù)讀取完畢,我會(huì)認(rèn)為這個(gè)客戶端可能完蛋了(一個(gè)常見的原因是 Pub/Sub 客戶端處理發(fā)布者的消息不夠快),于是斷開連接。
一共分為三種不同類型的客戶端,分別設(shè)置不同的限制。
- normal(普通),普通客戶端,包括 MONITOR 客戶端。
- replica(副本客戶端),slave 節(jié)點(diǎn)的客戶端。
- pubsub(發(fā)布訂閱客戶端),至少訂閱了一個(gè) pubsub 頻道或者模式的客戶端。
client-output-buffer-limit的語法如下。
表示不同類型的客戶端,當(dāng)客戶端的緩沖區(qū)內(nèi)容大小達(dá)到后我就立馬斷開與這個(gè)客戶端的連接,或者達(dá)到并持續(xù)了秒后斷開。
默認(rèn)情況下,普通客戶端不會(huì)限制,只有后異步的客戶端才可能發(fā)送發(fā)送請(qǐng)求的速度比讀取響應(yīng)速度快的問題。比如 pubsub 和 replica 客戶端會(huì)有默認(rèn)的限制。
soft limit 或者 hard limit 設(shè)置為 0,表示不啟用此限制。默認(rèn)配置如下。
client-query-buffer-limit
每個(gè)客戶端都有一個(gè) query buffer(查詢緩沖區(qū)或輸入緩沖區(qū)),用于保存客戶端發(fā)送命令,Redis Server 從 query buffer 獲取命令并執(zhí)行。
如果程序的 Key 設(shè)計(jì)不合理,客戶端使用大量的 query buffer,導(dǎo)致 Redis 很容易達(dá)到 maxmeory 限制。最好限制在一個(gè)固定的大小來避免占用過大內(nèi)存的問題。
如果你需要發(fā)送巨大的 multi/exec 請(qǐng)求的時(shí)候,那可以適當(dāng)修改這個(gè)值以滿足你的特殊需求。
默認(rèn)配置為 client-query-buffer-limit 1gb。
maxmemory-clients
這是 7.0 版本特性,每個(gè)與服務(wù)端建立連接的客戶端都會(huì)占用內(nèi)存(查詢緩沖區(qū)、輸出緩沖區(qū)和其他緩沖區(qū)),大量的客戶端可能會(huì)占用過大內(nèi)存導(dǎo)致 OOM,為了避免這個(gè)情況,我提供了一種叫做(Client Eviction)客戶端驅(qū)逐機(jī)制用于限制內(nèi)存占用。
配置方式有兩種。
- 具體內(nèi)存值,maxmemory-clients 1g來限制所有客戶端占用內(nèi)存總和。
- 百分比,maxmemory-clients 5% 表示客戶端總和內(nèi)存占用最多為 Redis 最大內(nèi)存配置的 5%。
默認(rèn)配置是 maxmemory-clients 0 表示無限制。
MySQL:“達(dá)到最大內(nèi)存限制,你會(huì)把所有客戶端連接都釋放么?”
不是的,一旦達(dá)到限制,我會(huì)優(yōu)先嘗試斷開使用內(nèi)存最多的客戶端。
proto-max-bulk-len
批量請(qǐng)求(單個(gè)字符串的元素)內(nèi)存大小限制,默認(rèn)是 proto-max-bulk-len 512mb,你可以修改限制,但必須大于等于 1mb。
hz
我會(huì)在后臺(tái)調(diào)用一些函數(shù)來執(zhí)行很多后臺(tái)任務(wù),比如關(guān)閉超時(shí)連接,清理不再被請(qǐng)求的過期的 key,rehash、執(zhí)行 RDB 內(nèi)存快照和 AOF 持久化等。
并不是所有的后臺(tái)任務(wù)都需要使用相同的頻率來執(zhí)行,你可以使用 hz 參數(shù)來決定執(zhí)行這些任務(wù)的頻率。
默認(rèn)配置是 hz 10,表示每秒執(zhí)行 10 次,更大的值會(huì)消耗更多的 CPU 來處理后臺(tái)任務(wù),帶來的效果就是更快的清理過期 key,清理的超時(shí)連接更精確。
這個(gè)值的范圍是 1~500,不過并不推薦設(shè)置大于 100 的值。大家使用默認(rèn)值就好,或者最多調(diào)高到 100。
dynamic-hz
默認(rèn)配置是 dynamic-hz yes,啟用 dynamic-hz 后,將啟用自適應(yīng) HZ 值的能力。hz 的配置值將會(huì)作為基線,Redis 服務(wù)中的實(shí)際 hz 值會(huì)在基線值的基礎(chǔ)上根據(jù)已連接到 Redis 的客戶端數(shù)量自動(dòng)調(diào)整,連接的客戶端越多,實(shí)際 hz 值越高,Redis 執(zhí)行定期任務(wù)的頻率就越高。
aof-rewrite-incremental-fsync
當(dāng)子進(jìn)程進(jìn)行 AOF 重寫時(shí),如果配置成 aof-rewrite-incremental-fsync yes,每生成 4 MB 數(shù)據(jù)就執(zhí)行一次 fsync操作,分批提交到硬盤來避免高延遲峰值,推薦開啟。
rdb-save-incremental-fsync
當(dāng)我在保存 RDB 內(nèi)存快照文件時(shí),如果配置成 db-save-incremental-fsync yes,每生成 4MB 文件就執(zhí)行一次 fsync操作,分批提交到硬盤來避免高延遲峰值,推薦開啟。
LFU 調(diào)優(yōu)
這個(gè)配置生效的前提是內(nèi)存淘汰策略設(shè)置的是 volatile-lfu或allkeys-lfu。
- lfu-log-factor 用于調(diào)整 Logistic Counter 的增長(zhǎng)速度,lfu-log-factor 值越大,Logistic Counter 增長(zhǎng)越慢。默認(rèn)配置 10。以下是表格是官方不同 factor 配置下,計(jì)數(shù)器的改變頻率。注意:表格是通過如下命令獲得的: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 用于調(diào)整 Logistic Counter 的衰減速度,它是一個(gè)以分鐘為單位的數(shù)值,默認(rèn)值為 1;lfu-decay-time 值越大,衰減越慢。
1.9 在線內(nèi)存碎片整理
MySQL:“什么是在線內(nèi)存碎片整理?”
Active (online) defragmentation 在線內(nèi)存碎片整理指的是自動(dòng)壓縮內(nèi)存分配器分配和 Redis 頻繁做更新操作、大量過期數(shù)據(jù)刪除,釋放的空間(不夠連續(xù))無法得到復(fù)用的內(nèi)存空間。
通常來說當(dāng)碎片化達(dá)到一定程度(查看下面的配置)Redis 會(huì)使用 Jemalloc 的特性創(chuàng)建連續(xù)的內(nèi)存空間, 并在此內(nèi)存空間對(duì)現(xiàn)有的值進(jìn)行拷貝,拷貝完成后會(huì)釋放掉舊的數(shù)據(jù)。這個(gè)過程會(huì)對(duì)所有的導(dǎo)致碎片化的 key 以增量的形式進(jìn)行。
需要注意的是
- 這個(gè)功能默認(rèn)是關(guān)閉的,并且只有在編譯 Redis 時(shí)使用我們代碼中的 Jemalloc 版本才生效。(這是 Linux 下的默認(rèn)行為)。
- 在實(shí)際使用中,建議是在 Redis 服務(wù)出現(xiàn)較多的內(nèi)存碎片時(shí)啟用(內(nèi)存碎片率大于 1.5),正常情況下盡量保持禁用狀態(tài)。
- 如果你需要試驗(yàn)這項(xiàng)特性,可以通過命令CONFIG SET activefrag yes來啟用。
清理的條件
activefrag yes:內(nèi)存碎片整理總開關(guān),默認(rèn)為禁用狀態(tài) no。
active-defrag-ignore-bytes 200mb:內(nèi)存碎片占用的內(nèi)存達(dá)到 200MB。
active-defrag-threshold-lower 20:內(nèi)存碎片的空間占比超過系統(tǒng)分配給 Redis 空間的 20% 。
在同時(shí)滿足上面三項(xiàng)配置時(shí),內(nèi)存碎片自動(dòng)整理功能才會(huì)啟用。
CPU 資源占用
MySQL:如何避免自動(dòng)內(nèi)存碎片整理對(duì)性能造成影響?
清理的條件有了,還需要分配清理碎片占用的 CPU 資源,保證既能正常清理碎片,又能避免對(duì) Redis 處理請(qǐng)求的性能影響。
active-defrag-cycle-min 5:自動(dòng)清理過程中,占用 CPU 時(shí)間的比例不低于 5%,從而保證能正常展開清理任務(wù)。
active-defrag-cycle-max 20:自動(dòng)清理過程占用的 CPU 時(shí)間比例不能高于 20%,超過的話就立刻停止清理,避免對(duì) Redis 的阻塞,造成高延遲。
整理力度
active-defrag-max-scan-fields 1000:碎片整理掃描到set/hash/zset/list 時(shí),僅當(dāng) set/hash/zset/list的長(zhǎng)度小于此閥值時(shí),才會(huì)將此鍵值對(duì)加入碎片整理,大于這個(gè)值的鍵值對(duì)會(huì)放在一個(gè)列表中延遲處理。
active-defrag-threshold-upper 100:內(nèi)存碎片空間占操作系統(tǒng)分配給 Redis 的總空間比例達(dá)此閾值(默認(rèn) 100%),我會(huì)盡最大努力整理碎片。建議你調(diào)整為 80。
jemalloc-bg-thread
默認(rèn)配置為 jemalloc-bg-thread yes,表示啟用清除臟頁后臺(tái)線程。
綁定 CPU
你可以將 Redis 的不同線程和進(jìn)程綁定到特定的 CPU,減少上下文切換,提高 CPU L1、L2 Cache 命中率,實(shí)現(xiàn)最大化的性能。
你可以通過修改配置文件或者taskset命令綁定。
可分為三個(gè)模塊。
- 主線程和 I/O 線程:負(fù)責(zé)命令讀取、解析、結(jié)果返回。命令執(zhí)行由主線程完成。
- bio 線程:負(fù)責(zé)執(zhí)行耗時(shí)的異步任務(wù),如 close fd、AOF fsync 等。
- 后臺(tái)進(jìn)程:fork 子進(jìn)程(RDB bgsave、AOF rewrite bgrewriteaof)來執(zhí)行耗時(shí)的命令。
Redis 支持分別配置上述模塊的 CPU 親合度,默認(rèn)情況是關(guān)閉的。
- server_cpulist 0-7:2,I/O 線程(包含主線程)相關(guān)操作綁定到 CPU 0、2、4、6。
- bio_cpulist 1,3,bio 線程相關(guān)的操作綁定到 CPU 1、3。
- aof_rewrite_cpulist,aof rewrite 后臺(tái)進(jìn)程綁定到 CPU 8、9、10、11。
- bgsave_cpulist 1,10-11,bgsave 后臺(tái)進(jìn)程綁定到 CPU 1、10、11。
注意事項(xiàng)
- Linux 下,使用「numactl --hardware」 查看硬件布局,確保支持并開啟 NUMA。
- 線程要盡可能分布在不同的 CPU,相同的 node,設(shè)置 CPU 親和度才有效,否則會(huì)造成頻繁上下文切換。
- 你要熟悉 CPU 架構(gòu),做好充分的測(cè)試。否則可能適得其反,導(dǎo)致 Redis 性能下降。