前言:本文是學習網易微專業的《python全棧工程師》 中的《服務器運維開發工程師》專題的課程筆記,歡迎學習交流。同時感謝老師們的精彩傳授!
一、課程目標
- 爲什麼需要緩存
memcache
安裝與使用- 緩存問題
二、詳情解讀
2.1.爲什麼需要緩存
2.1.1 網頁緩存
我們負面訪問久了,電腦裏會有很多瀏覽緩存,隔一段時間需要清理一下釋放空間,網頁在瀏覽器的緩坡是客戶端緩存,可以在nginx
中配置緩存有效期
2.1.2.服務器緩存
在我們開發的系統功能中,幾乎都是對數據庫的CURD
操作,因此當系統同時接受多個用戶併發訪問的時候,就會遇到數據庫瓶頸。
因爲數據庫需要從磁盤中讀取數據以及向磁盤寫入數據,而磁盤的讀取速度相對於整個系統的其他部分,很慢,因此數據庫訪問是一個瓶頸。
解決這個問題的方式:
No1
.數據庫集羣 - 方案比較昂貴,複雜(主從架構+讀寫分離)
讀寫分離可以提高系統的性能,但是該方案比較昂貴,考慮到集羣間的數據同步,比較複雜。
No2
.啓用緩存,減少直接訪問數據庫。
比如,文章的內容基本上不變,那麼可以生成好靜態的緩存,這樣避免每次訪問文章,就需要讀取mysql
2.1.3.緩存數據庫
能夠提供緩存服務的數據庫,他們大多數以鍵值對形式存儲數據。這類數據庫不需要SQL
語句查詢,所以以稱爲NoSQL - Not Only SQL
,表示除了關係型數據庫之外的另一種數據存儲方式的選擇。
有這麼幾種常用NoSQL
數據庫:
1.memcache
- 使用最便捷的緩存庫
2.redis
- 支持更多數據類型的緩存庫,可以利用他的列表類型實現隊列
3.mongodb
- 文檔型數據庫,支持索引,範圍搜索,排序,有些時候,可以單獨使用
2.1.4.緩存類型
緩存數據庫存儲方式:
1.將緩存寫入內存 - 內存的速度很快,但是關機後,數據會丟失
2.將緩存寫入內存,每隔一段時間將緩存刷入到硬盤
2.2.memcached
簡介
memcached
資料:
memcached
官方網站:http://memcached.org
安裝:
wget http://memcached.org/latest
tar -zxvf memcached-1.x.x.tar.gz
cd memcached-1.x.x
yum install libevent-devel
./configure && make && make test && sudo make install
運行服務器:
memcached -u root -d
-u
指定用戶運行,生產環境不要用root
用戶
-d
後臺守護進程
-h
幫助信息
2.3.memcache
客戶端模塊
1.安裝:
pip install python-memcached
還有其他的客戶端,包括pymemcache、django-pymemcache
2.使用客戶端:
mc = memcache.Client([host], debug=True)
3.設置和獲取緩存的值:
mc.set
mc.get
......
代碼示例:
# pip install python-memcached
# memcache 內容可以被多個進程共享
import memcache
import os, sys
from multiprocessing import Process
import time
import random
args = sys.argv
# memcached默認端口是11211
host = '192.168.1.3:11211'
mc = memcache.Client([host],debug=True)
# memcached集羣[(host:port,weight)]
# mc = memcache.Client([('ip:port', 1),('ip:port', 1)], debug=True)
# 添加-add 修改-replace 刪除-delete 取值 - get
# mc.add(key, value, time)
# mc.set(key, value, time)
# time 過期時間
'''
mc.set("name", "luxp")
mc.set("name", "luxp", 3)
name = mc.get('name')
'''
#mc.replace(key,value),如果key不存在,返回False
'''
mc.replace("name", "luxp", 3)
mc.set("name", "luxp", 3)
'''
# 一次set多個值
'''
dicts = {"key1":10, "key2":20, "key3":30 }
mc.set_multi(dicts)
'''
# 刪除
'''
mc.delete("key1")
mc.delete_multi(["key1", "key2"])
'''
# 一次取出多個值
'''
mc.get_multi(["key1", "key2"])
'''
# 加減
'''
mc.incr(key,val)
mc.decr(key,val)
'''
# 清空
'''
mc.flush_all()
'''
# 多進程共享數據
def write2mem(server):
mc = memcache.Client(server, debug=True)
while True:
time.sleep(3)
print("寫入memcache")
mc.set("key1", random.random())
def read2mem(server):
mc = memcache.Client(server, debug=True)
while True:
value = mc.get("key1")
if value:
print("value=", value)
mc.delete("key1")
if __name__ == "__main__":
server = [host]
t1 = Process(target=write2mem, args=(server,))
t2 = Process(target=read2mem, args=(server,))
t1.start()
t2.start()
add()
方法只能添加不存在的鍵名,如果鍵名存在則返回False
set()
方法可以修改已經存在的鍵名,如果鍵名不存在,則添加這個鍵名
replace()
方法可以修改已經存在的項
mc.set("name", "luxp")
mc.set("name", "luxp", 3)
name = mc.get('name')
mc.replace(key,value)
,如果key
不存在,返回False
mc.replace("name", "luxp", 3)
mc.set("name", "luxp", 3)
注意,memcache
不適合做隊列,上面的示例只是演示!
memcache
在flask
中的應用示例:
# -*- coding=utf-8 -*-
from flask import Flask, request
from settings import config
# pipenv install Flask-PyMemcache
import memcache
from hashlib import md5
app= Flask(__name__)
app.config.from_object(config['development'])
mc = memcache.Client(['192.168.3.40:11211'],debug=True)
@app.route("/")
def index():
print("full_path:",request.full_path)
print(md5(request.full_path.encode()).hexdigest())
# return mc.get("username")+ "hello world"
return "hello world"
# 啓用緩存要注意緩存更新策略
# 內容發生更新後,需要更新緩存,比較複雜
# 一定時間後,緩存更新
@app.route("/page/<int:page>")
def get_lists(page):
key = md5(request.full_path.encode()).hexdigest()
print(key)
res = mc.get(key)
if res:
return res+"<b>從memcache中讀取</b>"
else:
print("讀取數據庫")
mc.set(key, "這是第%s頁內容" % page, time=10)
return "這是第%s頁內容 <b>從數據庫中讀取</b>" % page
2.5.緩存策略問題
2.5.1.緩存更新策略:
1.緩存如果不及時更新,可能數據屬於無效。
2.如果定時更新,需要接受數據更新延時。
3.如果數據更新頻繁,導致緩存不斷更新,也會導致系統性能變差。
2.5.2.緩存命中率:
1.緩存數據佔用內存,緩存越多,佔用內存越多,意味着成本上升
2.緩存利用率很低,即查詢命中率,比如緩存了10000
個快照,只有10
個經常讀取的
3.需要根據業務情況調整緩存策略
2.5.3.緩存穿透:
1.緩存邏輯是如果緩存不存在就去數據庫查詢
2.如果某些查詢,數據庫查詢也沒有結果,那麼就會也沒有緩存
3.結果導致這些查詢始終查詢數據庫,解決方案是緩存空對象
2.5.4.緩存雪崩:
1.採用緩存系統後,大部分訪問都由緩存提供
2.如果緩存服務器發生故障,大量請求就直接湧向數據庫
3.最終直接導致整個系統崩潰
4.解決方法就是爲緩存層設計高可用架構
5.數據庫隔離,即使緩存層喪失功能,也不能讓所有請求湧向數據庫,以便儘快恢復緩存。
2.5.5.緩存預熱:
1.如果系統存在大量的緩存
2.在啓動整個系統的時候,會出現大量的數據庫請求,從而導致緩存加載失敗
3.解決辦法就是分批預先加載
三、課程小結
- 01 緩存作用
- 02
memcache
緩存庫 - 03
python
客戶端 - 04 緩存策略