# 第十四章:memcached
# memcached
### 什么是memcached:
1. `memcached`之前是`danga`的一個項目,最早是為LiveJournal服務的,當初設計師為了加速LiveJournal訪問速度而開發的,后來被很多大型項目采用。官網是`www.danga.com`或者是`memcached.org`。
2. `Memcached`是一個高性能的**分布式**的**內存對象緩存**系統,全世界有不少公司采用這個緩存項目來構建大負載的網站,來分擔數據庫的壓力。`Memcached`是通過在內存里維護一個統一的巨大的hash表,`memcached`能存儲各種各樣的數據,包括圖像、視頻、文件、以及數據庫檢索的結果等。簡單的說就是將數據調用到內存中,然后從內存中讀取,從而大大提高讀取速度。
3. 哪些情況下適合使用`Memcached`:存儲驗證碼(圖形驗證碼、短信驗證碼)、登錄session等所有不是至關重要的數據。
### 安裝和啟動`memcached`:
1. windows:
- 安裝:`memcached.exe -d install`。
- 啟動:`memcached.exe -d start`。
2. linux(ubuntu):
- 安裝:`sudo apt install memcached`
- 啟動:
```
<pre class="calibre12">```
cd /usr/local/memcached/bin
./memcached -d start
```
```
3. 可能出現的問題:
- 提示你沒有權限:在打開cmd的時候,右鍵使用管理員身份運行。
- 提示缺少`pthreadGC2.dll`文件:將`pthreadGC2.dll`文件拷貝到`windows/System32`.
- 不要放在含有中文的路徑下面。
4. 啟動`memcached`:
- `-d`:這個參數是讓`memcached`在后臺運行。
- `-m`:指定占用多少內存。以`M`為單位,默認為`64M`。
- `-p`:指定占用的端口。默認端口是`11211`。
- `-l`:別的機器可以通過哪個ip地址連接到我這臺服務器。如果是通過`service memcached start`的方式,那么只能通過本機連接。如果想要讓別的機器連接,就必須設置`-l 0.0.0.0`。
如果想要使用以上參數來指定一些配置信息,那么不能使用`service memcached start`,而應該使用`/usr/bin/memcached`的方式來運行。比如`/usr/bin/memcached -u memcache -m 1024 -p 11222 start`。
### `telnet`操作`memcached`:
`telnet ip地址 [11211]`
1. 添加數據:
- `set`:
- 語法:```
<pre class="calibre12">```
set key flas(是否壓縮) timeout value_length
value
```
```
- 示例:```
<pre class="calibre12">```
set username <span class="hljs-params">0</span> <span class="hljs-params">60</span> <span class="hljs-params">7</span>
zhiliao
```
```
- `add`:
- 語法:```
<pre class="calibre12">```
add key flas(<span class="hljs-params">0</span>) timeout value_length
value
```
```
- 示例:
```
<pre class="calibre12">```
add username <span class="hljs-params">0</span> <span class="hljs-params">60</span> <span class="hljs-params">7</span>
xiaotuo
```
```
`set`和`add`的區別:`add`是只負責添加數據,不會去修改數據。如果添加的數據的`key`已經存在了,則添加失敗,如果添加的`key`不存在,則添加成功。而`set`不同,如果`memcached`中不存在相同的`key`,則進行添加,如果存在,則替換。
2. 獲取數據:
- 語法:```
<pre class="calibre12">```
get key
```
```
- 示例:```
<pre class="calibre12">```
get username
```
```
3. 刪除數據:
- 語法:```
<pre class="calibre12">```
delete key
```
```
- 示例:```
<pre class="calibre12">```
delete username
```
```
- `flush_all`:刪除`memcached`中的所有數據。
4. 查看`memcached`的當前狀態:
- 語法:`stats`。
### 通過`python`操作`memcached`:
1. 安裝:`python-memcached`:`pip install python-memcached`。
2. 建立連接:
```
<pre class="calibre12">```
<span class="hljs-keyword">import</span> memcache
mc = memcache.Client([<span class="hljs-string">'127.0.0.1:11211'</span>,<span class="hljs-string">'192.168.174.130:11211'</span>],debug=<span class="hljs-keyword">True</span>)
```
```
3. 設置數據:
```
<pre class="calibre12">```
mc.set(<span class="hljs-string">'username'</span>,<span class="hljs-string">'hello world'</span>,time=<span class="hljs-params">60</span>*<span class="hljs-params">5</span>)
mc.set_multi({<span class="hljs-string">'email'</span>:<span class="hljs-string">'xxx@qq.com'</span>,<span class="hljs-string">'telphone'</span>:<span class="hljs-string">'111111'</span>},time=<span class="hljs-params">60</span>*<span class="hljs-params">5</span>)
```
```
4. 獲取數據:
```
<pre class="calibre12">```
mc.get(<span class="hljs-string">'telphone'</span>)
```
```
5. 刪除數據:
```
<pre class="calibre12">```
mc.delete(<span class="hljs-string">'email'</span>)
```
```
6. 自增長:
```
<pre class="calibre12">```
mc.incr(<span class="hljs-string">'read_count'</span>)
```
```
7. 自減少:
```
<pre class="calibre12">```
mc.decr(<span class="hljs-string">'read_count'</span>)
```
```
### memcached的安全性:
`memcached`的操作不需要任何用戶名和密碼,只需要知道`memcached`服務器的ip地址和端口號即可。因此`memcached`使用的時候尤其要注意他的安全性。這里提供兩種安全的解決方案。分別來進行講解:
1. 使用`-l`參數設置為只有本地可以連接:這種方式,就只能通過本機才能連接,別的機器都不能訪問,可以達到最好的安全性。
2. 使用防火墻,關閉`11211`端口,外面也不能訪問。
```
<pre class="calibre12">```
ufw enable # 開啟防火墻
ufw disable # 關閉防火墻
ufw default deny # 防火墻以禁止的方式打開,默認是關閉那些沒有開啟的端口
ufw deny 端口號 # 關閉某個端口
ufw allow 端口號 # 開啟某個端口
```
```
### 在Django中使用memcached:
首先需要在`settings.py`中配置好緩存:
```
<pre class="calibre12">```
CACHES = {
<span class="hljs-string">'default'</span>: {
<span class="hljs-string">'BACKEND'</span>: <span class="hljs-string">'django.core.cache.backends.memcached.MemcachedCache'</span>,
<span class="hljs-string">'LOCATION'</span>: <span class="hljs-string">'127.0.0.1:11211'</span>,
}
}
```
```
如果想要使用多臺機器,那么可以在`LOCATION`指定多個連接,示例代碼如下:
```
<pre class="calibre12">```
CACHES = {
<span class="hljs-string">'default'</span>: {
<span class="hljs-string">'BACKEND'</span>: <span class="hljs-string">'django.core.cache.backends.memcached.MemcachedCache'</span>,
<span class="hljs-string">'LOCATION'</span>: [
<span class="hljs-string">'172.19.26.240:11211'</span>,
<span class="hljs-string">'172.19.26.242:11211'</span>,
]
}
}
```
```
配置好`memcached`的緩存后,以后在代碼中就可以使用以下代碼來操作`memcached`了:
```
<pre class="calibre12">```
<span class="hljs-keyword">from</span> django.core.cache <span class="hljs-keyword">import</span> cache
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index</span><span class="hljs-params">(request)</span>:</span>
cache.set(<span class="hljs-string">'abc'</span>,<span class="hljs-string">'zhiliao'</span>,<span class="hljs-params">60</span>)
print(cache.get(<span class="hljs-string">'abc'</span>))
response = HttpResponse(<span class="hljs-string">'index'</span>)
<span class="hljs-keyword">return</span> response
```
```
需要注意的是,`django`在存儲數據到`memcached`中的時候,不會將指定的`key`存儲進去,而是會對`key`進行一些處理。比如會加一個前綴,會加一個版本號。如果想要自己加前綴,那么可以在`settings.CACHES`中添加`KEY_FUNCTION`參數:
```
<pre class="calibre12">```
CACHES = {
<span class="hljs-string">'default'</span>: {
<span class="hljs-string">'BACKEND'</span>: <span class="hljs-string">'django.core.cache.backends.memcached.MemcachedCache'</span>,
<span class="hljs-string">'LOCATION'</span>: <span class="hljs-string">'127.0.0.1:11211'</span>,
<span class="hljs-string">'KEY_FUNCTION'</span>: <span class="hljs-keyword">lambda</span> key,prefix_key,version:<span class="hljs-string">"django:%s"</span>%key
}
}
```
```
- Introduction
- 第一章:學前準備
- 第一節:虛擬環境
- 第二節:準備工作
- 第三節:Django介紹
- 第四節:URL組成部分
- 第二章:URL與視圖
- 第一節:第一個Django項目
- 第二節:視圖與URL分發器
- 第三章:模板
- 第一節:模板介紹
- 第二節:模板變量
- 第三節:常用標簽
- 第四節:常用過濾器
- 第五節:自定義過濾器
- 第七節:模版結構優化
- 第八節:加載靜態文件
- 第四章:數據庫
- 第一節:MySQL相關軟件
- 第二節:數據庫操作
- 第三節:ORM模型
- 第四節:模型常用字段
- 第五節:外鍵和表關系
- 第六節:增刪改查操作
- 第七節:查詢操作
- 第八節:QuerySet API
- 第九節:ORM模型遷移
- 第十節:ORM作業
- 第十一節:ORM作業參考答案
- 第十二節:Pycharm連接數據庫
- 第五章:視圖高級
- 第一節:限制請求method
- 第二節:頁面重定向
- 第三節:HttpRequest對象
- 第四節:HttpResponse對象
- 第五節:生成CSV文件
- 第六節:類視圖
- 第七節:錯誤處理
- 第六章:表單
- 第一節:表單概述
- 第二節:用表單驗證數據
- 第三節:ModelForm
- 第四節:文件上傳
- 第七章:cookie和session
- 第八章:上下文處理器和中間件
- 第一節:上下文處理器
- 第二節:中間件
- 第九章:安全
- 第一節:CSRF攻擊
- 第二節:XSS攻擊
- 第三節:點擊劫持攻擊
- 第四節:SQL注入
- 第十章:信號
- 第一節:什么是信號
- 第十一章:驗證和授權
- 第一節:概述
- 第二節:用戶對象
- 第三節:權限和分組
- 第十二章:Admin系統
- 第十三章:Django的緩存
- 第十四章:memcached
- 第十五章:Redis