概述
優(yōu)化了一次前后端處理不當(dāng)導(dǎo)致的CPU的一次爆機(jī)行為,當(dāng)然,這和服務(wù)器的配置低也有著密不可分的關(guān)系,簡(jiǎn)單的邏輯學(xué)告訴我們,要找到真正的問題,進(jìn)行解決,CPU爆機(jī)的關(guān)鍵點(diǎn)在于前后端兩個(gè)方面,下面針對(duì)具體的問題,進(jìn)行分析和解決。
定位問題
看監(jiān)控的圖表,CPU已經(jīng)達(dá)到了100%,但是內(nèi)存的使用曲線很平緩(也說明內(nèi)存沒有被合理的使用),大概率是代碼或者循環(huán)中產(chǎn)生的問題,服務(wù)器進(jìn)程處理產(chǎn)生多條阻塞,產(chǎn)生的積壓,導(dǎo)致的崩潰。
服務(wù)端Join影響了性能
順著代碼分析,找到了影響性能的幾個(gè)關(guān)鍵點(diǎn),服務(wù)端導(dǎo)致性能慢的關(guān)鍵點(diǎn)在于18w的用戶表分別和26w的評(píng)估記錄表、88w的訓(xùn)練動(dòng)作表、19w的用戶簽到表進(jìn)行Join所產(chǎn)生的進(jìn)程處理緩慢,下面我們用explan工具分別看一下所在的性能差別。
Mysql主要看到的是type和rows的指標(biāo),下面的語句告訴我們是全量(all)掃描了179223條數(shù)據(jù),優(yōu)化到了range級(jí)別的349條。
+----+-------------+-------+------+-------------------+---------+---------+----------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-------------------+---------+---------+----------+--------+----------------------------------------------+
| 1 | SIMPLE | u | ALL | PRIMARY,origin_id | NULL | NULL | NULL | 179223 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | a | ref | user_id | user_id | 4 | cc.u.uid | 1 | Using where |
+----+-------------+-------+------+-------------------+---------+---------+----------+--------+----------------------------------------------+
2 rows in set (0.01 sec)
+----+-------------+---------------+-------+---------------+---------+---------+------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+-------+---------------+---------+---------+------+------+-----------------------------+
| 1 | SIMPLE | cc_assessment | range | user_id | user_id | 4 | NULL | 349 | Using where; Using filesort |
+----+-------------+---------------+-------+---------------+---------+---------+------+------+-----------------------------+
1 row in set (0.01 sec)
和上面的問題差不多,都是全量檢索了80w+數(shù)據(jù),優(yōu)化后range方式檢索了1.2w+條數(shù)據(jù)。
+----+-------------+-------+--------+-------------------+---------+---------+--------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------+---------+---------+--------------+--------+-------------+
| 1 | SIMPLE | t | ALL | user_id | NULL | NULL | NULL | 881949 | Using where |
| 1 | SIMPLE | u | eq_ref | PRIMARY,origin_id | PRIMARY | 4 | cc.t.user_id | 1 | Using where |
+----+-------------+-------+--------+-------------------+---------+---------+--------------+--------+-------------+
+----+-------------+-----------------+-------+---------------+---------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------+-------+---------------+---------+---------+------+-------+-------------+
| 1 | SIMPLE | cc_train_action | range | user_id | user_id | 4 | NULL | 12979 | Using where |
+----+-------------+-----------------+-------+---------------+---------+---------+------+-------+-------------+
1 row in set (0.02 sec)
Mysql以page為基礎(chǔ),采用Be+Tree的結(jié)構(gòu)存儲(chǔ)在硬盤中,對(duì)硬盤的I/O傳輸效率非常明顯和敏感,一般的CPU爆機(jī)可能產(chǎn)生的情況就是代碼中的循環(huán)和遞歸使用的不當(dāng),還有一種可能的情況就是Mysql的Sql使用的不當(dāng)導(dǎo)致的。
代碼字典式拼接
之前的查詢寫在了循環(huán)里,數(shù)據(jù)多的時(shí)候,Mysql需要進(jìn)行反復(fù)的連接、查詢、斷開影響性能,這個(gè)地方也進(jìn)行了優(yōu)化。
$areaList = $this->area_model->get_info(['id' => $areaAllIds], '', '', '', 'id,name');
$areaNameDict = array_column($areaList, 'name', 'id');
foreach ($user_infos as $key => $val) {
//數(shù)組拼接
$user_infos[$key]['province_name'] = isset($areaNameDict[$val['native_province_id']]) ? $areaNameDict[$val['native_province_id']] : '';
}
大膽使用內(nèi)存
因?yàn)閮?nèi)存的曲線較為平緩,說明內(nèi)存不是導(dǎo)致問題的關(guān)鍵行為,PHP-FPM的特性在子進(jìn)程執(zhí)行結(jié)束也會(huì)進(jìn)行釋放,所以在進(jìn)程執(zhí)行時(shí)要保證內(nèi)存的合理使用,可以一次性的加載數(shù)據(jù)。
ini_set('memory_limit', '1024M');
前段的定時(shí)器
Http的每一次請(qǐng)求,服務(wù)器都會(huì)對(duì)應(yīng)開啟一個(gè)進(jìn)程,進(jìn)行處理和響應(yīng),前段的小伙伴使用定時(shí)器每分鐘進(jìn)行一次請(qǐng)求,導(dǎo)致的直接結(jié)果就是服務(wù)器進(jìn)入了多條等待導(dǎo)致的阻塞,直接到CPU打滿。
和前端的小伙伴溝通和協(xié)商,30分鐘請(qǐng)求一次服務(wù),就變的平穩(wěn)和絲滑了,至此這個(gè)問題告一段落了。
最后
我曾經(jīng)一度認(rèn)為不停的學(xué)習(xí)和鉆研技術(shù)就能做到技術(shù)人中的天花板,就可以所向無敵,還是賣炭翁的一句【我亦無他 唯手熟爾】點(diǎn)醒了我,其實(shí)就分熟練和不熟練2種 有2點(diǎn)要糾正自己和分享給朋友們,技術(shù)人更高維度是要學(xué)會(huì)合作、溝通和理解,協(xié)商的解決問題,Tcp、Http、Udp都是協(xié)議,都是請(qǐng)求和響應(yīng)的雙方達(dá)成一致,進(jìn)行的通信。文章來源:http://www.zghlxwxcb.cn/news/detail-810249.html
當(dāng)然,要保持良好的學(xué)習(xí)習(xí)慣和修煉技能的純度,也是必不可少的。文章來源地址http://www.zghlxwxcb.cn/news/detail-810249.html
到了這里,關(guān)于優(yōu)化 - 重構(gòu)一次Mysql導(dǎo)致服務(wù)器的OOM的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!