首頁>技術>

眾所周知Redis的作者對於Windows作業系統並不感冒,目前大部分公司都會將Web伺服器、資料庫伺服器等部署在Linux作業系統上,Redis也不例外。所以接下來介紹Linux作業系統如何最佳化Redis,包含如下七個方面。

一. 記憶體分配控制1. vm.overcommit_memory

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作業系統對大部分申請記憶體的請求都回復yes,以便能執行更多的程式。因為申請記憶體後,並不會馬上使用記憶體,這種技術叫做overcommit。如果Redis在啟動時有上面的日誌,說明vm.overcommit_memory=0,Redis提示把它設定為1。

vm.overcommit_memory用來設定記憶體分配策略,它有三個可選值,如下表所示。

vm.overcommit_memory含義0表示核心將檢查是否有足夠的可用記憶體。如果有足夠的可用記憶體,記憶體申請透過,否則記憶體申請失敗,並把錯誤返回給應用程序1表示核心允許超量使用記憶體直到用完為止2表示核心決不過量的("never overcommit")使用記憶體,即系統整個記憶體地址空間不能超過swap+50%的RAM值,50%是overcommit_ratio預設值,此引數同樣支援修改

注意:本文的可用記憶體代表物理記憶體與swap之和。

日誌中的Background save代表的是bgsave和bgrewriteaof,如果當前可用記憶體不足,作業系統應該如何處理fork。如果vm.overcommit_memory=0,代表如果沒有可用記憶體,就申請記憶體失敗,對應到Redis就是fork執行失敗,在Redis的日誌會出現:

Cannot allocate memory 

Redis建議把這個值設定為1,是為了讓fork能夠在低記憶體下也執行成功。

2. 獲取和設定獲取:
cat /proc/sys/vm/overcommit_memory0
設定:
echo "vm.overcommit_memory=1" >> /etc/sysctl.confsysctl vm.overcommit_memory=1
3. 最佳實踐Redis設定合理的maxmemory,保證機器有20%~30%的閒置記憶體。集中化管理aof重寫和rdb的bgsave。設定vm.overcommit_memory=1,防止極端情況下,會造成fork失敗。二. swappiness1. 引數說明

swap對於作業系統來比較重要,當物理記憶體不足時,可以swap out一部分記憶體頁,以解燃眉之急。但世界上沒有免費午餐,swap空間由硬碟提供,對於需要高併發、高吞吐的應用來說,磁碟IO通常會成為系統瓶頸。在Linux中,並不是要等到所有物理記憶體都使用完才會使用到swap,系統引數swppiness會決定作業系統使用swap的傾向程度。swappiness的取值範圍是0~100,swappiness的值越大,說明作業系統可能使用swap的機率越高,swappiness值越低,表示作業系統更加傾向於使用物理記憶體。swap的預設值是60,瞭解這個值的含義後,有利於Redis的效能最佳化。下表對swappiness的重要值進行了說明。

swapniess策略0Linux3.5以及以上:寧願OOM killer也不用swapLinux3.4以及更早:寧願swap也不要OOM killer1Linux3.5以及以上:寧願swap也不要OOM killer60預設值100作業系統會主動地使用swap

運維提示:OOM(Out Of Memory) killer機制是指Linux作業系統發現可用記憶體不足時,強制殺死一些使用者程序(非核心程序),來保證系統有足夠的可用記憶體進行分配。

從下表中可以看出,swappiness引數在Linux 3.5版本前後的表現並不完全相同,Redis運維人員在設定這個值需要關注當前作業系統的核心版本。

2. 設定方法

swappiness設定方法如下:

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

但是上述方法在系統重啟後就會失效,為了讓配置在重啟Linux作業系統後立即生效,只需要在/etc/sysctl.conf追加 vm.swappiness={bestvalue}即可。

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

需要注意/proc/sys/vm/swappiness是設定操作,/etc/sysctl.conf是追加操作。

3. 如何監控swap(1) 檢視swap的總體情況

Linux提供了free命令來查詢作業系統的記憶體使用情況,其中也包含了swap的相關使用情況。下面是某臺Linux伺服器執行free –m(以兆為到位)的結果,其中需要重點關注的是最後一行的swap統計,從執行結果看,swap一共有4095M,使用了0M,空閒了4095M。

             total       used       free     shared    buffers     cachedMem:         64385      31573      32812          0        505      10026-/+ buffers/cache:      21040      43344Swap:         4095          0       4095

在另一臺Linux伺服器同樣執行free -m,這臺伺服器開啟了8189M swap,其中使用了5241M。

             total       used       free     shared    buffers     cachedMem:         24096       8237      15859          0        136       2483-/+ buffers/cache:       5617      18479Swap:         8189       5241       2947
(2) 實時檢視swap的使用

Linux提供了vmstat命令查詢系統的相關效能指標,其中包含負載、CPU、記憶體、swap、IO的相關屬性。但其中和swap有關的指標是si和so,它們分別代表了作業系統的swap in和swap out。下面是執行vmstat 1(每隔一秒輸出)的效果,可以看到si和so都為0,代表當前沒有使用swap。

# vmstat  1procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st 1  0      0 33593468 517656 10271928    0    0     0     1    0    0  8  0 91  0  0  4  0      0 33594516 517656 10271928    0    0     0     0 10606 9647 10  1 90  0  0  1  0      0 33594392 517656 10271928    0    0     0     0 11490 10244 11  1 89  0  0  6  0      0 33594292 517656 10271928    0    0     0    36 12406 10681 13  1 87  0  0 
(3) 檢視指定程序的swap使用情況

Linux作業系統中,/proc/{pid}目錄是儲存指定程序的相關資訊,其中/proc/{pid}/smaps是記錄了當前程序所對應的記憶體映像資訊,這個資訊對於查詢指定程序的swap使用情況很有幫助。下面以一個Redis例項進行說明 透過info server獲取Redis的程序號process_id:

redis-cli -h ip -p port info server | grep process_idprocess_id:986

透過cat /proc/986/smaps查詢Redis的smaps資訊,由於有多個記憶體塊資訊,這裡只輸出一個記憶體塊映象資訊進行觀察。

2aab0a400000-2aab35c00000 rw-p 2aab0a400000 00:00 0 Size:            712704 kBRss:             617872 kBShared_Clean:         0 kBShared_Dirty:         0 kBPrivate_Clean:    15476 kBPrivate_Dirty:   602396 kBSwap:             58056 kBPss:             617872 kB

其中Swap欄位代表該記憶體塊存在swap分割槽的資料大小。透過執行如下命令,就可以找到每個記憶體塊映象資訊中,這個程序使用到的swap量,透過求和就可以算出總的swap用量。

cat /proc/986/smaps | grep SwapSwap:                 0 kBSwap:                 0 kB…Swap:                 0 kBSwap:            478320 kB…Swap:               624 kBSwap:                 0 kB
4. 最佳實踐

如果Linux>3.5,vm.swapniess=1,否則vm.swapniess=0,從而實現如下兩個目標:

物理記憶體充足時候,使Redis足夠快。物理記憶體不足時候,避免Redis死掉(如果當前Redis為高可用,死掉比阻塞更好)。三. Transparent Huge Pages

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.

從提示看Redis建議修改Transparent Huge Pages (THP)的相關配置,Linux kernel在2.6.38核心增加了Transparent Huge Pages (THP)特性 ,支援大記憶體頁(2MB)分配,預設開啟。當開啟時可以降低fork子程序的速度,但fork之後,每個記憶體頁從原來4KB變為2MB,會大幅增加重寫期間父程序記憶體消耗。同時每次寫命令引起的複製記憶體頁單位放大了512倍,會拖慢寫操作的執行時間,導致大量寫操作慢查詢。例如簡單的incr命令也會出現在慢查詢中。因此Redis日誌中建議將此特性進行禁用,禁用方法如下:

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

而且為了使機器重啟後THP配置依然生效,可以在/etc/rc.local中追加echo never > /sys/kernel/mm/transparent_hugepage/enabled。

在設定THP配置時需要注意:有些Linux的發行版本沒有將THP放到/sys/kernel/mm/transparent_hugepage/enabled中,例如Red Hat 6以上的THP配置放到/sys/kernel/mm/redhat_transparent_hugepage/enabled中。而Redis原始碼中檢查THP時,把THP位置寫死。

FILE *fp = fopen("/sys/kernel/mm/transparent_hugepage/enabled","r");if (!fp) return 0;   

所以在發行版中,雖然沒有THP的日誌提示,但是依然存在THP所帶來的問題。

echo never >  /sys/kernel/mm/redhat_transparent_hugepage/enabled
四. OOM killer

OOM killer會在可用記憶體不足時選擇性的殺掉使用者程序,它的執行規則是怎樣的,會選擇哪些使用者程序“下手”呢?OOM killer程序會為每個使用者程序設定一個權值,這個權值越高,被“下手”的機率就越高,反之機率越低。每個程序的權值存放在/proc/{progress_id}/oom_score中,這個值是受/proc/{progress_id}/oom_adj的控制,oom_adj在不同的Linux版本的最小值不同,可以參考Linux原始碼中oom.h(從-15到-17)。當oom_adj設定為最小值時,該程序將不會被OOM killer殺掉,設定方法如下。

echo {value} > /proc/${process_id}/oom_adj

對於Redis所在的伺服器來說,可以將所有Redis的oom_adj設定為最低值或者稍小的值,降低被OOM killer殺掉的機率。

for redis_pid in $(pgrep -f "redis-server")do  echo -17 > /proc/${redis_pid}/oom_adjdone
運維提示:有關OOM killer的詳細細節,可以參考Linux原始碼mm/oom_kill.c中oom_badness函式。筆者認為oom_adj引數只能起到輔助作用,合理的規劃記憶體更為重要。通常在高可用情況下,被殺掉比僵死更好,因此不要過多依賴oom_adj配置五. 使用NTP

NTP(Network Time Protocol)網路時間協議,一種保證不同機器時鐘一致性的服務。我們知道像Redis Sentinel和Redis Cluster這兩種需要多個Redis例項的型別,可能會涉及多臺伺服器。雖然Redis並沒有對多個伺服器的時鐘有嚴格的要求,但是假如多個Redis例項所在的伺服器時鐘不一致,對於一些異常情況的日誌排查是非常困難的,例如Redis Cluster的故障轉移,如果日誌時間不一致,對於我們排查問題帶來很大的困擾(注:但不會影響叢集功能,叢集節點依賴各自時鐘)。一般公司裡都會有NTP服務用來提供標準時間服務,從而達到糾正時鐘的效果(如下圖所示),為此我們可以每天定時去同步一次系統時間,從而使得叢集中的時間是統一。

例如每小時的同步1次NTP服務

0 * * * * /usr/sbin/ntpdate ntp.xx.com > /dev/null 2>&1
六. ulimit

在Linux中,可以透過ulimit檢視和設定系統的當前使用者程序的資源數。其中ulimit -a命令包含的open files引數,是單個使用者同時開啟的最大檔案個數。

# ulimit –a…max locked memory       (kbytes, -l) 64max memory size         (kbytes, -m) unlimitedopen files                      (-n) 1024pipe size            (512 bytes, -p) 8…

Redis允許同時有多個客戶端透過網路進行連線,可以透過配置maxclients來限制最大客戶端連線數。對Linux作業系統來說這些網路連線都是檔案控制代碼。假設當前open files是4096,那麼啟動Redis時會看到如下日誌。

# You requested maxclients of 10000 requiring at least 10032 max file descriptors.# Redis can’t set maximum open files to 10032 because of OS error: Operation not permitted.# Current maximum open files is 4096. Maxclients has been reduced to 4064 to compensate for low ulimit. If you need higher maxclients increase ‘ulimit –n’.

上面的日誌解釋如下:

第一行:Redis建議把open files至少設定成10032,那麼這個10032是如何來的呢?因為maxclients的預設是10000,這些是用來處理客戶端連線的,除此之外,Redis內部會使用最多32個檔案描述符,所以這裡的10032 = 10000 + 32。第二行:Redis不能將open files設定成10032,因為它沒有許可權設定。第三行:當前系統的open files是4096,所以maxclients被設定成4096-32=4064個,如果你想設定更高的maxclients,請使用ulimit -n來設定。從上面的三行日誌分析可以看出open files的限制優先順序比maxclients大。open files的設定方法如下:
ulimit –Sn {max-open-files}
七. TCP backlog

Redis預設的tcp-backlog為511,可以透過修改配置tcp-backlog進行調整,如果Linux的tcp-backlog小於Redis設定的tcp-backlog,那麼在Redis啟動時會看到如下日誌:

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

檢視方法:

cat /proc/sys/net/core/somaxconn128

修改方法:.

17
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 在Netty服務被N次攻擊之後,終於抓到現行了