WordPress優(yōu)化:為anylink插件增加緩存
編輯:狂族晨曦 來源:WordPress技巧 日期:2020-11-24 閱讀: 2,517 次 2 條評論 » 百度已收錄
先森最近在梳理網(wǎng)站的代碼,想辦法為網(wǎng)站加速,主要從代碼、軟件、網(wǎng)絡(luò)層面進(jìn)行優(yōu)化,這一切都是從網(wǎng)站切換到HTTPS開始的。
先森已經(jīng)連續(xù)觀察了多日的CDN了,目前也就到了查缺補(bǔ)漏的階段了。先森還將整個網(wǎng)站目前備份到了另一臺服務(wù)器,將網(wǎng)站在本地解析到這臺服務(wù)器上,開始了對代碼的檢查。開啟了debug,把大的一些問題都處理了,然后也把主題的代碼理了一遍,并且網(wǎng)站也加上了Redis緩存。但是先森發(fā)現(xiàn),即使加上了Redis,有時候網(wǎng)頁打開生成時間還是得一秒多,先森就很納悶,一直想搞明白到底是什么情況。
排查工具
很早以前,先森就在主題的footer.php末尾,添加了下面的代碼,以便于登錄之后可以看到當(dāng)前網(wǎng)頁的查詢次數(shù),生成時間:
<?php if (is_user_logged_in()){
echo "<pre>".get_num_queries().'次查詢,用時';
timer_stop(3);
echo '秒</pre>';
?>
這個代碼網(wǎng)絡(luò)上到處都是,相信很多人都添加的有。先森網(wǎng)站加Redis之前,網(wǎng)頁的查詢次數(shù)都是150+次,生成時間2-3秒,甚至更多。用上之后減少到50+次,但是有時還是會需要1秒多,讓先森百思不得其解。
然后先森把主題代碼該優(yōu)化的都優(yōu)化后,查詢次數(shù)30+次,生成時間降到1秒左右,但是先森還是不太滿足,所以想看看到底是執(zhí)行了哪些查詢,然后就在網(wǎng)上找到了這段代碼,和上面的有些類似。
首先需要先在WordPress的根目錄配置文件wp-config.php中添加保存查詢的代碼:
define('SAVEQUERIES', true);
然后也是在footer.php的網(wǎng)頁最后部分添加打印代碼:
<?php
if (current_user_can('administrator')){
global $wpdb;
echo "<pre>";
print_r($wpdb->queries);
echo "</pre>";
}
?>
但是先森添加后看了一下,差點(diǎn)當(dāng)場去世,這樣打印出來的是一個很大的多維數(shù)組,看的人眼花繚亂,重點(diǎn)是太長了還顯示不全。先森將打印復(fù)制出來,拿到NotePad++里面打開,依舊顯得很亂。

查詢的打印
不過大概看了一下,大數(shù)組的每一個鍵值表示一個查詢,然后一個查詢數(shù)組了,第一個值是執(zhí)行的SQL,第二個值是使用的時間,第三個值是調(diào)用的代碼位置。其實(shí)可以用循環(huán)做一個網(wǎng)格,讓前端顯示看著方便一點(diǎn),但是先森很懶,網(wǎng)上看了一下,有插件可以做到相關(guān)功能,且不用修改wp-config.php,即Debug Queries,所以先森就懶得自己寫了,直接裝了一個來進(jìn)行排查。
需要注意的是,Debug Queries很久沒有更新了,安裝可能會報錯,不過還是可以正常使用的。其實(shí)Debug Queries介紹頁也推薦使用Debug Objects插件,但是先森試了一下Debug Queries可以用,也就懶得再試另一個插件了。
排查問題
工具準(zhǔn)備好了,先森就來好好排查到底是哪里查詢比較慢了。
插件裝好了,再去看打印出來的查詢信息,就比較清晰了。先森對比了一下,大部分的查詢都是0.00x秒的,就是幾毫秒的,但是只要涉及到wp_al_urls的查詢,就會是即時甚至上百毫秒。

wp_al_urls的查詢
先森看了一下,這個表是插件anylink的,這個插件主要是將網(wǎng)站上的外鏈全都轉(zhuǎn)化成內(nèi)鏈,點(diǎn)擊后可以跳轉(zhuǎn)到外鏈。
對于anylink,先森這里也發(fā)過兩篇相關(guān)的文章:
這個插件先森也是從建站伊始就在用了,是一個很好用的插件,但沒有想到這個插件會出現(xiàn)慢查詢。
通過上面的截圖可以看到,對wp_al_urls的查詢條件是網(wǎng)站鏈接,看了一下數(shù)據(jù)庫,這個SQL是為了去拿到內(nèi)鏈的slug記錄:

anylink獲取slug
這里去查的,實(shí)際上是網(wǎng)頁正文里的外鏈、各位評論大佬的網(wǎng)址對應(yīng)的內(nèi)鏈地址。
先森看了一下這個表,沒想到竟然有10M的大小,接近10萬條數(shù)據(jù),而且這里查詢的是al_origURL字段,先森看了一下,這個字段是沒有索引的。
解決問題
對于MySQL的查詢,先森能想到的優(yōu)化方法就是加索引,所以先森直接就操作加索引,但是報錯了:

給al_origURL字段加索引報錯
看報錯是跟字段格式有關(guān)的,看了一下這個字段的類型是mediumtext的,這個字段是存URL的,有些URL非常的長,如果該varchar的話,可能會出問題,varchar最長255個字符。網(wǎng)上找了一陣子解決方案,都是說text相關(guān)的類型無法加索引。先森本來就對數(shù)據(jù)庫索引什么的不太了解,所以只能放棄這條路。
先森還能想到的辦法,就是看下這個查詢的代碼,想辦法把結(jié)果存到Redis上緩存起來。至于怎么找到實(shí)際執(zhí)行的代碼,先森看了一下,直接找調(diào)用的最后一段就可以了。

找到慢查詢的調(diào)用代碼
可以看到,兩個SQL實(shí)際上是一樣的,查的是同個網(wǎng)址,結(jié)果執(zhí)行的時間竟然都比較長,所以確實(shí)得把結(jié)果緩存起來。
為了優(yōu)化代碼,先森把整個網(wǎng)站都作為了一個PhpStorm里的一個項(xiàng)目,不得不說一個好的IDE工具寫起代碼來是真的舒服。直接全局搜索,尋找get_slug_by_url這個函數(shù),順利找到了代碼所在。

搜索get_slug_by_url函數(shù)
這里有兩個結(jié)果,第一個是原本的函數(shù),已經(jīng)被先森注釋起來了,第二個是先森改了之后的。
可以看到這個函數(shù)就是調(diào)用$wpdb來執(zhí)行SQL語句,將得到的結(jié)果再返回一下。函數(shù)比較簡單,也很利于先森修改。
然后先森又找了一下WordPress如何添加緩存,結(jié)果找到一下,發(fā)現(xiàn)非常簡單。
WordPress操作緩存
WordPress 為我們提供了使用對象緩存的函數(shù),方便我們使用對象緩存。wp_cache_add() :添加數(shù)據(jù)到緩存中,如果數(shù)據(jù)已存在,返回 flase
wp_cache_set() :添加數(shù)據(jù)到緩存中,如果數(shù)據(jù)已存在,會覆蓋數(shù)據(jù)
wp_cache_get() :獲取緩存中的數(shù)據(jù),如果數(shù)據(jù)不存在,返回 false
wp_cache_delete() : 從緩存中刪除數(shù)據(jù)
wp_cache_replace() :替換緩存中的數(shù)據(jù),類似 wp_cache_set,但是如果數(shù)據(jù)不存在,不自動添加
wp_cache_flush():清除所有緩存
如果沒有裝redis緩存插件,上面的這些函數(shù)是在./wp-includes/cache.php里。如果裝了Redis Object Cache等插件,就會自動增加一個./wp-content/object-cache.php文件,這些函數(shù)也會存在于這個文件中,用于存入緩存。
WordPress 對象緩存使用使用示例
$result = wp_cache_get( 'my_result' );
if ( false === $result ) {
$result = $wpdb->get_results( $query );
wp_cache_set( 'my_result', $result );
}
對anylink的get_slug_by_url函數(shù)改造
有了上面這個案例,先森為anylink的函數(shù)增加緩存就很方便了。示例很簡單,get_slug_by_url函數(shù)本身也簡單,所以改造后如下:
public function get_slug_by_url( $url ) {
$arr_slug = wp_cache_get( $url );
if ( false === $arr_slug ) {
global $wpdb;
$arr_slug = array();
$arr_slug = $wpdb->get_row($wpdb->prepare(
"SELECT *
FROM " . ANYLNK_DBTB . "
WHERE al_origURL = %s",
$url
), ARRAY_A);
wp_cache_set( $url, $arr_slug );
}
return $arr_slug;
}
因?yàn)槭纠秃瘮?shù)太契合了,所以這個函數(shù)幾乎就和示例結(jié)構(gòu)一樣。首先去Redis獲取緩存數(shù)據(jù),獲取不到就去MySQL查詢,查到后再存到Redis。
2022年4月4日更新:此代碼存在億點(diǎn)點(diǎn)bug,修復(fù)參考此文章:
檢查效果
代碼修改后,同步到測試服務(wù)器,訪問了兩次之前訪問的頁面,查詢次數(shù)和用時都降下來了。然后看到查詢次數(shù)還是有33次,其中有部分是查詢wp_al_urls_index這個表的,雖然速度不慢,但是次數(shù)比較多,先森重復(fù)上面的方法也修改了一下相關(guān)函數(shù),最終效果如下圖:

最終效果
查看Redis的keys
上面改造的代碼中,是拿url地址去做的key名稱,那么先森也來看下緩存數(shù)據(jù)在Redis里的情況:
![]()
redis的緩存
上面改造的代碼比較簡陋,直接拿的URL做的key名稱,如果URL比較短還好,如果長的話就可能出現(xiàn)問題,key名稱其實(shí)可以做一下長度限制。
提示:Redis最好不要使用默認(rèn)端口6379,除非安全做的非常好。使用Redis時注意以下幾點(diǎn):
1、一定要配置強(qiáng)密碼;
2、安全組、防火墻一定要最小范圍放通Redis端口,即針對指定IP放通訪問;
3、盡量不要使用默認(rèn)端口。
因?yàn)镽edis而導(dǎo)致服務(wù)器中木馬病毒的保障,先森這邊經(jīng)常遇到。
總結(jié)
先森以前以為給WordPress配上Redis很麻煩,實(shí)際使用發(fā)現(xiàn)真香,建議有能力的朋友都上一下,畢竟生命不止,折騰不息。本文最主要的還是記錄一下排查網(wǎng)頁查詢慢的過程和解決方法,希望能夠給其他朋友提供思路。
轉(zhuǎn)載請注明出處來自http://www.cnidcc.cn/anylink_redis_cache.html

川公網(wǎng)安備 51011202000104號
感謝分享,謝謝站長!!
支持一下交個朋友