Redis開發運維的陷阱及避坑指南

後青春期的Keats發表於2020-04-27

原文首發於部落格園,作者:後青春期的Keats;地址:https://www.cnblogs.com/keatsCoder/ 轉載請註明,謝謝!

Linux 配置優化

我們在使用 Redis 過程中,可能更多的關注 Redis 本身的一些配置優化,如 AOF、RDB 配置、資料結構配置優化等。但是很少關心 Redis 的載體,伺服器的優化。而這往往為我們的專案執行帶來災難性的打擊。因此伺服器優化也是必不可少的

記憶體分配控制

Redis啟動時,可能會出現下面的日誌

# WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

overcommit 是 Linux 的一種記憶體處理機制:Linux 對絕大多數記憶體申請都會回覆 yes,以便執行更多的程式。因為申請記憶體後,並不會馬上使用記憶體。這種機制就是 overcommit 。

而 overcommit_memory 是用來設定記憶體分配策略的,有三種取值

含義
0 核心檢查是否有足夠可用記憶體,有則通過。沒有則申請失敗,並返回錯誤給程式
1 表示核心允許超量使用記憶體直到用完為止
2 表示核心絕不過量的使用記憶體

日誌中 Background save 指的是 bgsave 和 bgrewriteaof 。根據作業系統的配置,如果 overcommit_memory 設定為 0 則可能會造成記憶體申請失敗而導致後臺持久化失敗。因此 Redis 建議將這個值設定為 1 是為了 fork 操作在低記憶體下也能執行成功。

設定方法

通過命令修改,立即生效。重啟後會失效

sysctl vm.overcommit_memory=1

再將改動寫入系統配置檔案,使其永久有效

echo "vm.overcommit_memory=1" >> /etc/sysctl.conf

建議

採用 Redis 建議的配置是為了在極端情況下 Linux 可以擠出來一些記憶體供 Redis 備份,但是更建議優先配置好 maxmemory ,給機器留 20%~30% 的空閒記憶體

硬碟虛擬記憶體

swap 是指當實體記憶體不足時,拿出部分硬碟空間當 SWAP 分割槽(虛擬成記憶體)使用。我們都知道硬碟的讀寫速度相對於記憶體實在是太雞肋,對於高併發、高吞吐的應用來說,磁碟IO通長會成為系統瓶頸。Linux 系統中 swappiness 的值控制作業系統使用 swap 的傾向程度。

檢視核心版本:

uname -sr
說明
0 核心版本 3.5 及以上 寧願使用 OOM Killer 也不使用 SWAP;核心版本 3.4 及更早則反之
1 核心版本 3.5 及以上 寧願使用 OOM Killer 也不使用 SWAP
60 預設值
主動使用 SWAP

PS:OOM Killer 是指當 Linux 發現作業系統記憶體不足時,主動殺死一些非核心程式的操作

設定方法

echo {value} > /proc/sys/vm/swappiness

echo vm.swappiness={value} >> etc/sysctl.conf

監控swap

檢視 Swap 的總體情況

free -m

1587991406036

最後一行即展示了 Swap 的使用情況,一共 2047 Mb,以使用 0 Mb,空閒 2047 Mb

實時檢視 Swap 的使用

1587991665139

引數 si 表示 swap in ,so 表示 swap out 在我的機器上都是 0 表示沒有使用交換

檢視指定程式的 Swap 情況

通過 ps -ef |grep redis 檢視 Redis 程式號,例如 1621

通過 cat /proc/1621/smaps | grep Swap 命令檢視每個記憶體塊 Redis Swap 的使用情況

THP 記憶體頁大小

Redis 啟動時可能會看到下面的日誌

WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.

提示告訴我們建議修改 Transparent Huge Pages (THP) 的配置,Linux kernel 在 2.6.38 核心增加了 THP 特性,支援大記憶體頁(2MB)分配,預設開啟。開啟後可加快 fork 子程式的速度,但是 fork 操作後,每個記憶體頁從原來的 4KB 變為 2MB,會大幅加重重寫期間父程式記憶體消耗。同時每次寫命令引起的複製記憶體頁單位放大了512倍。會拖慢寫操作的執行時間。造成大量的寫操作慢查詢因此 Redis 日誌中建議禁用它。方法如下:

echo never > /sys/kernel/mm/transparent_hugepage/enabled

另外在 /etc/rc.local 中追加

echo never > /sys/kernel/mm/transparent_hugepage/enabled

對於某些發行版本(例如紅帽6以上)配置檔案不在這個位置(在 /sys/kernel/mm/redhat_transparent_hugepage/enabled),但是 Redis 檢查 THP 是寫死的此位置,所以雖然這麼修改後 Redis 不報警然而實際是沒有作用的,需要注意。應該改動對應位置的值

使用NTP 同步時間

在叢集或哨兵環境中,多臺伺服器使用相同的網路時間協議同步時間能更方便的閱讀日誌,排查問題

可以設定定時任務同步時間

crontab -u //設定某個使用者的cron服務
crontab -l //列出某個使用者cron服務的詳細內容
crontab -r //刪除某個使用者的cron服務
crontab -e //編輯某個使用者的cron服務
crontab -i //列印提示,輸入yes等確認資訊

新增每小時執行一次的任務

0 * * * * /usr/sbin/ntpdate cn.pool.ntp.org > dev/null 2>&1

最大連線數限制

通過 ulimit -a 命令檢視和設定當前使用者程式的資源數,其中包含 open files 引數,是單個使用者同時開啟的最大檔案描述符個數。雖然 Redis 中可以配置最大的客戶端連線數(預設 10000) 。Redis 內部最多使用 32 個檔案描述符。當 open files = 4096 時,Redis 最大提供 4096-32=4064 個連線。因為它不能突破作業系統的限制。如果需要,使用如下命令修改:

ulimit -Sn {max-open-files}

TCP backlog

tcp backlog 配置的是 tcp 握手時候的佇列大小。如果該值過小。會導致高併發場景下部分連線第三次握手ACK被丟棄。關於 backlog

The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

Redis 啟動時,會告訴我們系統配置中該值是 128,而 Redis 511。這個 511 是沒用的,因為系統比這個小。需要修改系統 backlog 的值

echo 511 > /proc/sys/net/core/somaxconn

參考文獻:

《Redis開發與運維》 --- 付 磊 張益軍

相關文章