在互聯網蓬勃發展的時代,相信大多數讀者都會碰到以下問題:前端等待後端發送數據的時間過長,除了造成用戶體驗不佳外,也會減少用戶訪問網站的意願,同時降低用戶的黏著度,以及增加用戶的脫落率;上述問題更是降低用戶轉換率、變現率的主要推手,意味著公司營利將受到嚴峻的考驗。
究其原因為當數據庫的資料日益增長,導致數據查詢過慢,除了可以透過slow-query log分析慢查詢的原因,優化Query的語句,或者是適時添加Index,提升數據查找速度,甚或是分庫分表、讀寫分離等。然而,遇到高併發的情況時,頻繁地訪問數據庫,數據庫性能仍會出現瓶頸,進而影響整體服務。
為了改善上述問題,本節將著重如何在後端開發時,添加Cache的機制,來減少對數據庫的I/O,進而優化後端的服務性能。由於筆者工作實務上經常以Flask框架進行API的開發,因此想與讀者們分享Flask-Caching的技術,縮短前端整體等待時間。
首先,我們先安裝Flask-Caching的套件pip3 install flask-caching
。
接著,我們創建app.py檔vim app.py
,並且初始化flask-caching的配置,如下所示。
from flask import Flask
from flask_caching import Cache
import timeconfig = {
"DEBUG": True,
"CACHE_TYPE": "SimpleCache",
}app = Flask(__name__)
app.config.from_mapping(config)
cache = Cache(app)
我們在撰寫視圖函數時,在函數上方加上@cache.memoize()的裝飾器,便可發揮Cache的功能,timeout參數代表需要緩存的時間,單位為秒,該參數可以根據實際開發需求進行調整。讓我們來模擬向MySQL請求數據的場景,感受一下Cache的威力吧!
@app.route("/")
@cache.memoize(timeout=50)
def index():
time.sleep(5)
print("inner index")
return "Cached for 50s"if __name__ == "__main__":
app.run(port=5050)

第一次請求 http://127.0.0.1:8000/時,我們需要等待5秒的時間,前端才會收到後端響應的數據,同時終端機會輸出inner index的字樣。但當用戶發出第二次請求時,我們會發現終端機會直接繞過index()中執行業務邏輯的代碼,並且立即返回Cache for 50s的結果,即代表該視圖函數的結果,已經被緩存了。相信讀者們能夠深刻感受到Cache強大的威力了!
除了能夠緩存視圖函數的結果,一般函數的返回結果也能被緩存,我們實作下面的例子:
@app.route("/app")
def cache_test():
cache_result()
return "Cached for 50s"@cache.memoize(timeout=50)
def cache_result():
print("cache not yet started …")
time.sleep(5)
return "cache_result"
在筆者實際開發中,會針對數據變動性較小、訪問次數頻繁以及QPS高的服務添加Cache功能,以避免流量尖峰壓垮DB性能。
接下來,我們將Cache的數據存入Redis中。Redis是一個基於Key-Value的NoSQL數據庫,支持各種數據類型,因資料全部存放於記憶體當中,可以完成實時的數據查找。
請讀者們確保Redis已安裝完畢。此時,我們需要安裝Redis的Python包pip3 install redis
,並且修改app.py中,關於CACHE_TYPE的配置。
config = {
"DEBUG": True,
"CACHE_TYPE": "redis",
"CACHE_REDIS_URL": "redis://localhost:6379",
}
如此一來,數據的結果便會儲存至Redis當中,我們可以到Redis中查看緩存的數據。

至此便介紹完Flask-caching的簡單操作,筆者會陸陸續續撰寫後端服務優化的文章,請讀者拭目以待。如讀者認為該篇文章有所助益,可多多分享並且拍手,表示對我的支持與鼓勵。