十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
Linux 進(jìn)程通過 C 標(biāo)準(zhǔn)庫(kù)中的內(nèi)存分配函數(shù) malloc 向系統(tǒng)申請(qǐng)內(nèi)存,但是到真正與內(nèi)核交互之間,其實(shí)還隔了一層,即內(nèi)存分配管理器(memory allocator)。常見的內(nèi)存分配器包括:ptmalloc(Glibc)、tcmalloc(Google)、jemalloc(FreeBSD)。MySQL 默認(rèn)使用的是 glibc 的 ptmalloc 作為內(nèi)存分配器。
作為一家“創(chuàng)意+整合+營(yíng)銷”的成都網(wǎng)站建設(shè)機(jī)構(gòu),我們?cè)跇I(yè)內(nèi)良好的客戶口碑。創(chuàng)新互聯(lián)建站提供從前期的網(wǎng)站品牌分析策劃、網(wǎng)站設(shè)計(jì)、網(wǎng)站設(shè)計(jì)、做網(wǎng)站、創(chuàng)意表現(xiàn)、網(wǎng)頁制作、系統(tǒng)開發(fā)以及后續(xù)網(wǎng)站營(yíng)銷運(yùn)營(yíng)等一系列服務(wù),幫助企業(yè)打造創(chuàng)新的互聯(lián)網(wǎng)品牌經(jīng)營(yíng)模式與有效的網(wǎng)絡(luò)營(yíng)銷方法,創(chuàng)造更大的價(jià)值。
內(nèi)存分配器采用的是內(nèi)存池的管理方式,處在用戶程序?qū)雍蛢?nèi)核層之間,它響應(yīng)用戶的分配請(qǐng)求,向操作系統(tǒng)申請(qǐng)內(nèi)存,然后將其返回給用戶程序。
為了保持高效的分配,分配器通常會(huì)預(yù)先向操作系統(tǒng)申請(qǐng)一塊內(nèi)存,當(dāng)用戶程序申請(qǐng)和釋放內(nèi)存的時(shí)候,分配器會(huì)將這些內(nèi)存管理起來,并通過一些算法策略來判斷是否將其返回給操作系統(tǒng)。這樣做的最大好處就是可以避免用戶程序頻繁的調(diào)用系統(tǒng)來進(jìn)行內(nèi)存分配,使用戶程序在內(nèi)存使用上更加高效快捷。
關(guān)于 ptmalloc 的內(nèi)存分配原理,個(gè)人也不是非常了解,這里就不班門弄斧了,有興趣的同學(xué)可以去看下華庭的《glibc 內(nèi)存管理 ptmalloc 源代碼分析》【文末鏈接】。
關(guān)于如何選擇這三種內(nèi)存分配器,網(wǎng)上資料大多都是推薦摒棄 glibc 原生的 ptmalloc,而改用 jemalloc 或者 tcmalloc 作為默認(rèn)分配器。因?yàn)?ptmalloc 的主要問題其實(shí)是內(nèi)存浪費(fèi)、內(nèi)存碎片、以及加鎖導(dǎo)致的性能問題,而 jemalloc 與 tcmalloc 對(duì)于內(nèi)存碎片、多線程處理優(yōu)化的更好。
目前 jemalloc 應(yīng)用于 Firefox、FaceBook 等,并且是 MariaDB、Redis、Tengine 默認(rèn)推薦的內(nèi)存分配器,而 tcmalloc 則應(yīng)用于 WebKit、Chrome 等。
查看 /proc/meminfo
Tips:
“大內(nèi)存頁”也稱傳統(tǒng)大頁、大頁內(nèi)存等有助于 Linux 進(jìn)行虛擬內(nèi)存的管理,標(biāo)準(zhǔn)的內(nèi)存頁為 4KB,這里使用“大內(nèi)存頁”最大可以定義 1GB 的頁面大小,在系統(tǒng)啟動(dòng)期間可以使用“大內(nèi)存頁”為應(yīng)用程序預(yù)留一部分內(nèi)存,這部分內(nèi)存被占用且永遠(yuǎn)不會(huì)被交換出內(nèi)存,它會(huì)一直保留在那里,直到改變配置。(詳細(xì)介紹請(qǐng)看下面鏈接官方解釋)
那么這么大頁內(nèi)存是分配給誰的呢?
查詢一下:
shell /proc/sys/vm/hugetlb_shm_group
27
shell id 27
uid=27(mysql) gid=27(mysql) groups=27(mysql)
hugetlb_shm_group 文件里填的是指定大頁內(nèi)存使用的用戶組 id,這里查看到是 MySQL 組 id,那既然是給 MySQL 的為什么 free 等于 total,并且 mysql 還只有 20 多 G 實(shí)際使用內(nèi)存呢?
原來在 MySQL 中還有專門啟用大內(nèi)存頁的參數(shù),在 MySQL 大內(nèi)存頁稱為 large page。
查看 MySQL 配置文件
發(fā)現(xiàn)配置文件中確實(shí)有 large-page 配置,但出于禁用狀態(tài)。
后與業(yè)務(wù)確認(rèn),很早之前確實(shí)啟用過 mysql 的 large page,不過后面禁用了。排查到這基本就有了結(jié)論。
結(jié)論
這套環(huán)境之前開啟了 20000 的大內(nèi)存頁,每頁大小為 2MB,占用了 40G 內(nèi)存空間,給 MySQL 使用,并且 MySQL 開啟了 large page,但后來不使用的時(shí)候,只關(guān)閉了 MySQL 端的 large page 參數(shù),但沒有實(shí)際更改主機(jī)的關(guān)于大內(nèi)存頁的配置,所以導(dǎo)致,實(shí)際上主機(jī)上的還存在 20000 的大內(nèi)存頁,并且沒在使用,這一部分長(zhǎng)期空閑,并且其他程序不能使用。
所以 MySQL 在使用 20G 內(nèi)存左右,整個(gè)主機(jī)內(nèi)存就飽和了,然后在部分條件下,就觸發(fā)了 OOM,導(dǎo)致 mysqld 被 kill,但主機(jī)上又有 mysqld_safe 守護(hù)程序,所以又再次給拉起來,就看到了文章初的偶爾連接不上的現(xiàn)象。
char: 是定長(zhǎng)格式的,長(zhǎng)度范圍是0~255. 想要儲(chǔ)存一個(gè)長(zhǎng)度不足255的字符時(shí),MySQL會(huì)用空格來填充剩下的字符。因此在讀取數(shù)據(jù)時(shí),char類型的數(shù)據(jù)要進(jìn)行處理,把后面的空格去除。
加入兩臺(tái)mysql,以前的規(guī)則是key%2 == 0 進(jìn)入庫(kù)1,key%2 == 1 進(jìn)入庫(kù)2。在擴(kuò)容方案中,可以將mysql配置信息修改為:庫(kù)1的主從作為兩臺(tái)機(jī)器,庫(kù)2同理,這樣key%4 == 0 和==2進(jìn)入庫(kù)1,key%4 == 1或3進(jìn)入庫(kù)2。然后再做數(shù)據(jù)的清除工作。