Linux筆記:高併發下的Web架構之Memcached緩存技術

概述

在我們把系統做好反向代理和負載均衡之後, 還有一個性能問題沒有解決,就是我們的數據庫,此時如果併發量大了,數據庫將是一個很大的瓶頸。假如我們有一臺4核8G的服務器, 它能承受的併發數通常也就在2000左右。以電商系統爲例, 如果所有的商品信息都是直接從數據庫中讀取, 首先掛掉的將會是我們的數據庫。爲了解決這個問題,在DB層和業務邏輯層之間, 會加入一層緩存, 利用緩存可以很好分擔數據庫的壓力。

緩存的分類

  • DNS
  • 瀏覽器
  • App
  • 代理緩存
  • 服務端緩存

服務端緩存中的內存緩存

  • 我們主要針對服務端緩存中的內存緩存來分析
  • 在RDB中,也就是我們所說的關係型數據庫,如MySQL、SQLServer等,數據保存在服務器的硬盤之中, 硬盤對數據存取比較慢
  • 普通筆記本轉速是5.4K轉/分鐘, 一般服務器硬盤轉速可以達到1.5W轉/分鐘, 這個速度和內存讀取來說也是非常慢的
  • 隨機訪問情況下, 內存訪問速度比硬盤訪問速度快上10萬倍以上
  • 然而內存對計算機來說是緊缺的資源, 我們無法將所有數據都放在內存中, 所以程序員開發了一些緩存算法來解決這些問題

緩存算法

  • LRU(Least Recently Used)

    • 最近最少使用
    • Memcached主要採用此算法來淘汰數據
  • LFU(Least Frequently Used)

    • 根據數據的歷史訪問頻率來淘汰數據

關於Memcached緩存

  • Memcached 是高性能的分佈式內存緩存系統,一般用來緩存訪問的熱點數據,以減輕數據庫負擔
  • 全球最大的Memcached用戶是facebook, 已經超過28T的數據存放在Memcached中, 使用了超過800臺的服務器
  • 官網:https://memcached.org/

Ubantu上Memcached的安裝

  • $apt update
  • $apt install -y memcached

Memcached的服務管理

  • $service memcached stop
  • $service memcached start
  • $service memcached restart

Memcached的配置

  • $vi /etc/memcached.conf
    • -d 守護進程
    • -m 內存, default 64MB , 這裏需要區分情況, 如果是專用的Memcached服務器可以把70%的系統內存分配
    • -u 運行用戶
    • -l 監聽的服務器IP地址
    • -p 監聽端口, 默認是11211
    • -c 併發連接數, 默認是1024
  • 如果編輯了之後,需要重啓服務才能生效, $service memcached restart
  • 連接Memcached終端, $telnet 127.0.0.1 11211 進入
    # 可以查看狀態
    stats
    # ... 此處輸出很多信息
    STAT pid 237784                     # 進程ID
    STAT uptime 2070631                 # 運行秒數
    STAT version 1.4.25                 # 版本
    STAT libevent 2.0.21-stable         # libevent版本
    STAT pointer_size 64                # 系統指針(32bit/64bit)
    STAT curr_items 50237               # 當前實例存儲的items數量
    STAT total_items 1337400            # 實例啓動以後存儲的items總數量
    STAT bytes 35169108                 # 實例存儲items佔用的字節數
    STAT curr_connections 349           # 當前打開的連接數 【重要指標】
    STAT total_connections 108429       # 實例啓動後打開的連接總數
    STAT cmd_get 14005676               # get 命令總請求次數
    STAT cmd_set 1337400                # set 命令總請求次數
    STAT get_hits 12596511              # 總命中次數 【重要指標】
    STAT get_misses 1409165             # 總未命中次數 【重要指標】
    STAT evictions 0                    # 爲獲取空閒內存而刪除的items數
    STAT bytes_read 4918928094          # 總讀取字節數(請求字節數)
    STAT bytes_written 46027378599      # 總髮送字節數(結果字節數)
    STAT limit_maxbytes 1572864000      # 分配的緩存大小
    STAT threads 4                      # 當前線程數
    
    # 退出
    quit
    
  • Memcached的使用比較簡單,我們很少在服務器上對它進行管理
  • Memcached是基於內存的, 如果服務關閉,則數據全部丟失

通過python來操作Memcached

1 ) 安裝

$ pip3 install python-memcached

2 ) 使用

import memcache

# 鏈接
mc = memcache.Client(['127.0.0.1:11211'])

# 存入
mc.set('name', 'python', 60) # 過期時間 單位爲秒

# 讀取
res = mc.get('name')

# 刪除
mc.delete('name')

Memcached的控制檯演示

  • 在windows上,如果我們想要啓動Memcached, 需要下載一個它的可執行程序memcached Server文件, 啓動它,開啓命令窗口
  • 打開另一個命令行使用pip安裝它的python擴展, $pip install python-memcached, 這裏是window一般使用pip命令即可
  • 然後開始進入python環境進行相關操作
    >>> import memcache
    >>> mc = memcache.Client(['127.0.0.1:11211'])
    >>> mc.set('name', 'jack')
    True
    >>> mc.get('name')
    'jack'
    >>> mc.delete('name')
    1
    >>> mc.get('name')
    >>>
    >>> mc.set('name', 'jack', 10)
    True
    >>> mc.get('name')
    'jack'
    >>> mc.get('name') # 10s之後再次get, 發現沒了
    >>>
    

Memcached的項目演示

1 ) 新建一個cache.py文件

  • 注意名稱不能和將要導入的memcache重名

2 ) 一般的數據庫操作

import pymysql

def get_data():
    conn = pymysql.connect(host='localhost', user='root', password='你自己設置的密碼', database='test', charset='utf8)
    cursor = conn.cursor
    sql = 'select * from product limit 3'
    cursor.execute(sql)
    data = cursor.fetchall()
    cursor.close()
    conn.close()
    return data

3 ) 改造後的帶Memcached緩存的數據庫操作

import pymysql
import memcache

def get_data():
    # 鏈接memcache
    mc = memcache.Client(['127.0.0.1:11211'])
    # 這裏定義一個公共變量, 防止後期修改一處, 忘記其他地方還有可能會造成的bug
    cacheKey = 'product_list'
    # 首先嚐試獲取,如果存在那麼直接使用
    res = mc.get(cacheKey')
    if res is not None:
        return res

    # 不存在則進行連接數據庫查詢
    print('go db now >>>>')
    conn = pymysql.connect(host='localhost', user='root', password='你自己設置的密碼', database='test', charset='utf8)
    cursor = conn.cursor
    sql = 'select * from product limit 3'
    cursor.execute(sql)
    data = cursor.fetchall()
    cursor.close()
    conn.close()

    # 沒有數據時將數據放入memcache, 這裏設置10s的有效時間 
    # 這個時間設置很重要, 需要根據不同的業務設置不同的時間, 這樣就可以靈活控制
    # 假如1s有300個併發, 那麼10s就是3000次的查詢, 這裏設置10s, 那麼在這10s內只會查詢1次的數據庫, 相比之下減少了2999次節約了很多資源
    # 一般業務我們可能會設置更長的時間, 如果數據更新了, 那麼數據仍不會變化, 這會造成一個問題, 
    # 解決方案是:當數據更新時, 將緩存刪除或者放入新的緩存數據
    mc.set(cacheKey, data, 10)

    return data
發佈了410 篇原創文章 · 獲贊 221 · 訪問量 69萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章