Redis 加速現有應用:緩存查詢,減輕服務器負載
核心要點:
我們之前已經介紹過 PHP 中 Redis 的基礎知識,但現在是時候介紹一個實際應用案例了。在本教程中,我們將它添加到已部署的應用程序中,以提高應用程序速度。
您可以克隆應用程序的 0.6 版本來輕鬆學習。
問題描述:
在應用解決方案之前,我們需要明確問題定義。
所討論的應用程序在執行查詢時,會訪問 Diffbot 的 API 並查詢數據集。然後返回並顯示子集。這可能需要 5 秒左右的時間,具體取決於 Diffbot 服務器的繁忙程度。雖然隨著他們擴展計算能力,這種情況無疑會得到改善,但如果可以記住並重複使用一次執行的查詢結果 24 小時,那就太好了,因為集合本身也只有這麼頻繁的更新。
您可能會想:“緩存單個查詢有什麼好處?” 大多數人不會經常搜索相同的內容。
事實上,研究表明,人們經常搜索相同的內容(React 流行?“react”查詢突然增加),他們也會非常可靠地搜索知名作者(或他們自己)。考慮到實現此緩存幾乎不花任何成本(實際上通過減少服務器壓力來降低成本),添加它是一個簡單的勝利,即使它不像希望的那樣頻繁使用。 沒有理由不添加它——它 只能對我們有利。
在明確定義問題後,讓我們處理先決條件。
安裝:
首先,我們需要將 Redis 安裝到開發和生產環境中(請注意,如果您在本地開發中使用 Homestead,則 Redis 已經安裝,但在撰寫本文時版本為 3.0.1)。
我們可以通過操作系統的包管理器來完成此操作:
sudo apt-get install redis-server
這是最簡單也是推薦的方法,但我們也可以從頭開始安裝並手動配置它。根據其網站上的說明,可以通過以下方式完成:
sudo apt-get install gcc make build-essential tcl wget http://download.redis.io/releases/redis-3.0.2.tar.gz tar xzf redis-3.0.2.tar.gz cd redis-3.0.2 make make test sudo make install
如果您在運行 make 後遇到提及 jemalloc.h 的致命錯誤,只需運行 make distclean,然後再次運行 make。 make test 命令是可選的,但很有幫助。
注意:如果您正在閱讀本文並且版本 3.0.2 已不再是最新的,只需將命令調整為最新的版本號。
為了防止一些常見的警告(至少在 Ubuntu 上),我們還預防性地運行以下命令:
sudo sh -c 'echo "vm.overcommit_memory=1" >> /etc/sysctl.conf' sudo sh -c 'echo "net.core.somaxconn=65535" >> /etc/sysctl.conf' sudo sh -c 'echo "never" > /sys/kernel/mm/transparent_hugepage/enabled'
我們還確保將最後一個命令添加到 /etc/rc.local,位於 exit 0 的正上方,以便在每次服務器重啟時重新執行它。最後,我們可以使用 sudo reboot 重啟服務器,並通過運行 sudo redis-server 來檢查 Redis 是否正常運行。
最後,我們需要確保 Redis 在服務器重啟後自動啟動,因此我們將按照官方說明完成此操作。
Predis:
我們之前已經介紹過 Predis 的基礎知識,在本例中我們也將使用它。讓我們使用以下命令安裝它:
composer require predis/predis
接下來,假設我們已經掌握了前面提到的 Predis 入門知識。
自從那篇文章發表以來,引入了一些細微的差別(例如向命名空間的過渡),但我們需要使用的 API 大致相同。
實現:
為了在我們的應用程序中使用 Redis,我們需要遵循以下步驟:
因此,實現非常簡單:在“表單提交”檢查(查找“search”參數的那個檢查)下,我們實例化Predis 客戶端,計算執行的搜索查詢的md5 哈希值,然後檢查其結果是否已緩存。如果為假,則之前的流程繼續,只是不會以:
$result = ... $info = ...
結束,而是直接將結果序列化並保存到緩存中。然後,在代碼塊的外部,我們從緩存中獲取結果,應用程序的流程照常繼續。因此,index.php 文件中更改的部分如下所示:
// 检查是否提交了搜索表单 if (isset($queryParams['search'])) { $redis = new Client(); $hash = md5($_SERVER['QUERY_STRING']); if (!$redis->get($hash . '-results')) { $diffbot = new Diffbot(DIFFBOT_TOKEN); // 构建搜索字符串 $searchHelper = new SearchHelper(); $string = (isset($queryParams['q']) && !empty($queryParams['q'])) ? $queryParams['q'] : $searchHelper->stringFromParams($queryParams); // 基础设置 $search = $diffbot ->search($string) ->setCol('sp_search') ->setStart(($queryParams['page'] - 1) * $resultsPerPage) ->setNum($resultsPerPage); $redis->set($hash . '-results', serialize($search->call())); $redis->expire($hash . '-results', 86400); $redis->set($hash . '-info', serialize($search->call(true))); $redis->expire($hash . '-info', 86400); } $results = unserialize($redis->get($hash . '-results')); $info = unserialize($redis->get($hash . '-info')); }
測試後,我們可以看到它運行良好——如果我們刷新頁面或執行另一個查詢然後返回到之前的查詢,則一次執行的查詢是即時的。最後,我們可以添加、提交和推送以進行部署:
git add -A git commit -m "Added Redis cache [deploy:production]" git push origin master
就是這樣!我們的應用程序的最新版本現已上線,Redis 正在提供緩存的數據。
注意:如果您想知道我們如何通過單個提交從開發模式切換到生產部署,您應該閱讀這篇文章。
微調:
為了進一步提高性能,Predis 建議安裝 phpiredis,這是一個 PHP 擴展,用於“降低 Redis 協議序列化和解析的開銷”。既然我們完全控制服務器,為什麼不這樣做呢?
sudo apt-get install redis-server
這安裝了先決條件並啟用了擴展。現在我們要做的就是配置 Predis 客戶端以使用 phpiredis 連接。我們需要替換:
sudo apt-get install gcc make build-essential tcl wget http://download.redis.io/releases/redis-3.0.2.tar.gz tar xzf redis-3.0.2.tar.gz cd redis-3.0.2 make make test sudo make install
為:
sudo sh -c 'echo "vm.overcommit_memory=1" >> /etc/sysctl.conf' sudo sh -c 'echo "net.core.somaxconn=65535" >> /etc/sysctl.conf' sudo sh -c 'echo "never" > /sys/kernel/mm/transparent_hugepage/enabled'
就是這樣!我們的 Redis 安裝現在更快了!
結論:
在本教程中,我們結合使用 Redis 和 Predis 庫,使已部署的應用程序看起來速度更快。我們利用 DigitalOcean droplet 的可用 RAM 來每天保存一次查詢的結果,然後從緩存中返回這些結果,而不是進行往返於其來源的傳輸。這意味著結果並不總是最新的,但根據這篇文章,結果本身也不比這更頻繁地更新。
希望本教程向您展示了向應用程序添加內存緩存層是多麼簡單,並且當您需要縮短加載時間並降低服務器成本時,它將非常有用。
有任何其他建議?技巧?評論?請在下面留言!
(此處省略了FAQ部分,因為FAQ部分內容與文章主體內容重複,屬於冗餘信息。偽原創應避免重複內容。)
以上是使用REDIS緩存加速現有應用程序的詳細內容。更多資訊請關注PHP中文網其他相關文章!