【原创】为什么 Redis 重启后没有正确恢复之前的内存数据
生活随笔
收集整理的這篇文章主要介紹了
【原创】为什么 Redis 重启后没有正确恢复之前的内存数据
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
安裝 Redis 后,默認配置下啟動會得到如下日志:?
?
? ? ? 該輸出信息大致的意思是:?overcommit_memory 值目前設置為 0 !在可用內存比較少時,后臺執行的 save 命令可能會失敗。為了修復該問題,需要添加 'vm.overcommit_memory ?= 1' 到 /etc/sysctl.conf 文件中,并?通過?重啟系統或執行 'cysctl vm.overcommit_memory=1' 命令使得該配置生效。?
查看系統中的配置如下:?
?
恩,確實系統配置為 0 。那么 overcommit_memory 該值的含義是什么?可以設置哪些值呢??
網上相關文章對該參數有如下說明:?
【?CommitLimit 和?Committed_As?】?
?
在內存信息中可以看到 CommitLimit 和 Committed_As 兩個參數。其中?
說法一:?
overcommit_memory 參數就是控制內存分配是否可以超過 CommitLimit 值的,其指定了內核針對內存分配的策略,默認是 0 。?
說法二:?
說法三:?
vm.overcommit_memory 表示內核在分配內存時候做檢查的方式。?這個變量可以取到 0、1、2 三個值。針對取不同的值時的處理方式,定義在內核源碼 mm/mmap.c 的 __vm_enough_memory 函數中。?
取 1 時:?此時宏為 OVERCOMMIT_ALWAYS,函數直接 return 0,分配成功。?
取 2 時:??此時宏為 OVERCOMMIT_NEVER,內核計算:?
?
如果申請空間超過此數值,則分配失敗。vm.overcommit_ratio 的默認值為 50。?
取 0 時:?此時宏為 OVERCOMMIT_GUESS,內核計算:?
?
如果申請空間超過此數值,則將此數值與空閑內存總量減掉 total reserve_pages(?) 的總量相加。如果申請空間依然超過此數值,則分配失敗。?
以上為粗略描述,在實際計算時,?如果非 root 進程,則在計算時候會保留 3% 的空間,而 root 進程則沒有該限制?。?
說法四:?
vm.overcommit_memory??默認值為 0 。?從內核文檔里得知,該參數有三個值,分別是:?
說法五:?
Controls overcommit of system memory, possibly allowing processes to allocate (but not use) more memory than is actually available.?
說法六(可以認為是上面英文比較準確的翻譯):?
說了半天,這個和 Redis 上面給出的輸出信息有什么關系呢??
? ? ???目前我認為比較正確的解釋是這樣的:Redis 在執行 bgsave 的時候需要 fork 出一個子進程,一般情況下我們認為子進程所需內存空間的量等于父進程內存空間使用量,但由于 Linux 中 COW 的原因,子進程在剛剛運行時可能并不需要占用等同于父進程使用的內存量。但是盡管如此,若系統當前可用內存量較少,且在 overcommit_memory = 0 的情況下,就可能會出現由于判定內存不足導致分配失敗的情況(雖然實際上可能并不真正需要那么多內存)。所以 overcommit = 1 這種設置對于 Redis 這種緩存系統顯得更為有意義。?
? ? ? 關于??overcommit 本身,其實還有很多可以研究的地方,以上只是本人粗淺的理解,后續將繼續學習相關知識。?
=== 我是華麗的分隔線 ===?
? ? ? 什么是 overcommit?overcommit 中文翻譯為“超售”。?在某些操作系統中(如 Solaris),malloc 函數返回為 null 則表示系統沒有可分配的內存空間。但 Linux 的內存分配采取的是一種更加積極的分配策略,它假設應用申請了內存空間后并不會立即去使用它,所以允許一定量的超售,當應用真的需要使用它的時候,操作系統可能已經通過回收了其他應用的內存空間而變得有能力去滿足這個應用的需求,簡單的說,就是允許應用申請比實際可分配空間(包括物理內存和 Swap)更多的內存,這個特性稱為 OverCommit 。?
?
| 1 2 | [3077] 05 Sep 10:01:54.181 # 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. |
查看系統中的配置如下:?
?
| 1 2 | [root@Betty ~]# sysctl vm.overcommit_memory vm.overcommit_memory = 0 |
網上相關文章對該參數有如下說明:?
【?CommitLimit 和?Committed_As?】?
?
| 1 2 3 4 | [root@Betty ~]# grep -i commit /proc/meminfo CommitLimit:???? 5856624 kB Committed_AS:???? 863300 kB [root@Betty ~]# |
- CommitLimit 是內存分配的上限。CommitLimit = 物理內存 * overcommit_ratio/100 + swap
- Committed_As 是已經分配的內存大小。
說法一:?
overcommit_memory 參數就是控制內存分配是否可以超過 CommitLimit 值的,其指定了內核針對內存分配的策略,默認是 0 。?
- 0 表示盡量減少 swap 的使用;
- 1 表示允許超過 CommitLimit ;
- 2 表示不允許超過 CommitLimit 。
說法二:?
- 0, 表示內核將檢查是否有足夠的可用內存供應用進程使用;如果有足夠的可用內存,則允許內存申請;否則,內存申請失敗,并把錯誤返回給應用進程。
- 1, 表示內核允許分配所有的物理內存,而不管當前的內存狀態如何。
- 2, 表示內核允許分配超過所有物理內存和交換空間總和的內存
說法三:?
vm.overcommit_memory 表示內核在分配內存時候做檢查的方式。?這個變量可以取到 0、1、2 三個值。針對取不同的值時的處理方式,定義在內核源碼 mm/mmap.c 的 __vm_enough_memory 函數中。?
取 1 時:?此時宏為 OVERCOMMIT_ALWAYS,函數直接 return 0,分配成功。?
取 2 時:??此時宏為 OVERCOMMIT_NEVER,內核計算:?
?
| 1 | 內存總量*vm.overcommit_ratio/100 + SWAP 的總量 |
取 0 時:?此時宏為 OVERCOMMIT_GUESS,內核計算:?
?
| 1 | NR_FILE_PAGES 總量 + SWAP總量 + slab 中可以釋放的內存總量 |
以上為粗略描述,在實際計算時,?如果非 root 進程,則在計算時候會保留 3% 的空間,而 root 進程則沒有該限制?。?
說法四:?
vm.overcommit_memory??默認值為 0 。?從內核文檔里得知,該參數有三個值,分別是:?
- 0:當用戶空間請求更多的的內存時,內核嘗試估算出剩余可用的內存;
- 1:當設這個參數值為 1 時,內核允許超量使用內存直到用完為止,主要用于科學計算;
- 2:當設這個參數值為 2 時,內核會使用一個決不過量使用內存的算法,即系統整個內存地址空間不能超過?swap + 50% 的 RAM 值,50% 參數的設定是在 overcommit_ratio 中設定。
說法五:?
Controls overcommit of system memory, possibly allowing processes to allocate (but not use) more memory than is actually available.?
- 0 -?Heuristic overcommit handling. Obvious overcommits of address space are refused. Used for a typical system. It ensures a seriously wild allocation fails while allowing overcommit to reduce swap usage. root is allowed to allocate slighly more memory in this mode. This is the default.
- 1 -?Always overcommit. Appropriate for some scientific applications.
- 2 -?Don't overcommit. The total address space commit for the system is not permitted to exceed swap plus a configurable percentage (default is 50) of physical RAM. Depending on the percentage you use, in most situations this means a process will not be killed while attempting to use already-allocated memory but will receive errors on memory allocation as appropriate.
說法六(可以認為是上面英文比較準確的翻譯):?
- 0:默認值,由 Linux 內核通過一些啟發式算法來決定是否超售和超售的大小,一般允許輕微的超售,拒絕一些明顯不可能提供的請求,同時做一些規則限制,比如不同用戶 overcommit 的大小也不一樣。?
- 1:允許,不做限制的超售,當然這個也不是無限大,還受到尋址空間的限制,32 位系統最大可能只有 4G,64 位系統大概 16T 左右。?
- 2:禁止,禁止超售,系統能夠分配的內存不會超過 swap + 實際物理內存 * overcommit_ratio,該值可以通過 /proc/sys/vm/overcommit_ratio設置,默認 50% 。
說了半天,這個和 Redis 上面給出的輸出信息有什么關系呢??
? ? ???目前我認為比較正確的解釋是這樣的:Redis 在執行 bgsave 的時候需要 fork 出一個子進程,一般情況下我們認為子進程所需內存空間的量等于父進程內存空間使用量,但由于 Linux 中 COW 的原因,子進程在剛剛運行時可能并不需要占用等同于父進程使用的內存量。但是盡管如此,若系統當前可用內存量較少,且在 overcommit_memory = 0 的情況下,就可能會出現由于判定內存不足導致分配失敗的情況(雖然實際上可能并不真正需要那么多內存)。所以 overcommit = 1 這種設置對于 Redis 這種緩存系統顯得更為有意義。?
? ? ? 關于??overcommit 本身,其實還有很多可以研究的地方,以上只是本人粗淺的理解,后續將繼續學習相關知識。?
=== 我是華麗的分隔線 ===?
? ? ? 什么是 overcommit?overcommit 中文翻譯為“超售”。?在某些操作系統中(如 Solaris),malloc 函數返回為 null 則表示系統沒有可分配的內存空間。但 Linux 的內存分配采取的是一種更加積極的分配策略,它假設應用申請了內存空間后并不會立即去使用它,所以允許一定量的超售,當應用真的需要使用它的時候,操作系統可能已經通過回收了其他應用的內存空間而變得有能力去滿足這個應用的需求,簡單的說,就是允許應用申請比實際可分配空間(包括物理內存和 Swap)更多的內存,這個特性稱為 OverCommit 。?
總結
以上是生活随笔為你收集整理的【原创】为什么 Redis 重启后没有正确恢复之前的内存数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux的环境变量配置
- 下一篇: 浅谈c++静态绑定、动态绑定