Python服務器運維筆記:第四章web性能優化 - 4.1.1.memcached緩存數據庫

前言:本文是學習網易微專業的《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不適合做隊列,上面的示例只是演示!

memcacheflask中的應用示例:

# -*- 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 緩存策略
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章