支付網(wǎng)站建設費/正規(guī)的培訓學校
小阿軒yx-高性能內(nèi)存對象緩存
案例分析
案例概述
Memcached
- 是一款開源的高性能分布式內(nèi)存對象緩存系統(tǒng)
- 用于很多網(wǎng)站提高訪問速度,尤其是需要頻繁訪問數(shù)據(jù)的大型網(wǎng)站
- 是典型的 C/S 架構,需要構建 Memcached 服務器端與 Memcached API 客戶端
- 用 C 語言編寫的,Memcached API 客戶端可用任何語言來編寫(如 PHP、Python、Perl等)
案例前置知識點
數(shù)據(jù)存儲方式與數(shù)據(jù)過期方式
Memcached
- 具有獨特的數(shù)據(jù)存儲方式和數(shù)據(jù)過期方式
數(shù)據(jù)存儲方式:Slab Allocation
- 按組分配內(nèi)存
數(shù)據(jù)過期方的兩種方式
- LRU
- Laxzy Expiration
LRU
- 指追加的數(shù)據(jù)空間不足時,會根據(jù) LRU 的情況淘汰最近最少使用的記錄
- 可以有效解決內(nèi)存碎片問題,但也可能會使內(nèi)存空間產(chǎn)生浪費
Laxzy Expiration
- 即懶惰過期,指使用 get 時查看記錄時間,從而檢查記錄是否已經(jīng)過期
Memcached 緩存機制
- 緩存是常駐在內(nèi)存的數(shù)據(jù),能夠快速進行讀取
- 是一款非常出色的緩存軟件
Memcached 分布式
- 部署主要依賴于 Memcached 的客戶端來實現(xiàn)
- 多個?Memcached 服務器是獨立的
- 數(shù)據(jù)如何存儲是由路由器算法所決定
Memcached 路由算法
求余數(shù) hash 算法
- 先用 key 做 hash 運算得到一個整數(shù),再做 hash 算法,根據(jù)余數(shù)進行路由,適合大多數(shù)據(jù)需求
- 不適合在動態(tài)變化環(huán)境中,比如大量機器添加或刪除,會導致大量的對象存儲位置失效
一致性 hash 算法
- 適合在動態(tài)變化的環(huán)境中使用
原理
- 按照 hash 算法把對應的 key 通過一定的 hash 算法處理后映射形成一個首尾相接閉合循環(huán)
- 然后通過使用與對象存儲一樣的 hash算法將機器也映射到環(huán)中
- 順時針方向計算將所有對象存儲到離自己最近的機器中
案例環(huán)境
- 使用三臺 CentOS 7.9 系統(tǒng)完成
- 兩臺是 Memcached 服務器,另一臺是基于 LAMP 架構進行 Memcached 擴展的 Memcached API 客戶端
主機 | 操作系統(tǒng) | 主機名/IP地址 | 主要軟件及版本 |
服務器 | CentOS7.9 | Memcache1/192.168.10.101 | libevent-2.1.8-stable.tar.gz |
服務器 | CentOS7.9 | Memcache2/192.168.10.102 | libevent-2.1.8-stable.tar.gz |
客戶端 | CentOS7.9 | Memcached-API/192.168.10.103 | httpd-2.4.25.tar.gz |
案例拓撲
案例需求
- 安裝部署 Memcached 服務
- 安裝 Memcached API 客戶端
- 實現(xiàn) Memcached 主主復制+高可用
案例實現(xiàn)思路
- 首先安裝 Memcached 服務器 及Memcached APl客戶端
- 利用 Keepalived 構建 Memcached 高可用服務器架構
- 測試并驗證 Keepalived 高可用所帶來的穩(wěn)定性
案例一
單 memcached 節(jié)點緩存系統(tǒng)
設置各節(jié)點的主機名
主機
- 192.168.10.101
[root@localhost ~]# hostnamectl set-hostname memcache1
[root@localhost ~]# bash
主機
- 192.168.10.102
[root@localhost ~]# hostnamectl set-hostname memcache2
[root@localhost ~]# bash
主機
- 192.168.10.103
[root@localhost ~]# hostnamectl set-hostname memcached-API
[root@localhost ~]# bash
安裝 Memcached 服務器
修改兩臺主機名
[root@localhost ~]# hostnamectl set-hostname memcache1
[root@localhost ~]# bash
[root@localhost ~]# hostnamectl set-hostname memcache2
[root@localhost ~]# bash
首先關閉防火墻、內(nèi)核機制
[root@memcache1 ~]# systemctl stop firewalld
[root@memcache1 ~]# setenforce 0
安裝?Libevent
上傳 libevent 包至服務器
解壓
[root@memcache1 ~]# tar zxvf libevent-2.1.8-stable.tar.gz
進入?libevent
[root@memcache1 ~]# cd libevent-2.1.8-stable
安裝 gcc* 環(huán)境
[root@memcache1 libevent ~]# yum -y install gcc*
?配置路徑前綴
[root@memcache1 libevent-2.1.8-stable]# ./configure --prefix=/usr/local/libevent
make install 執(zhí)行
[root@memcache1 libevent-2.1.8-stable]# make && make install
Libevent
- 是用 C 語言編寫
- 輕量級
- 開源高性能事件通知庫
- 已經(jīng)被廣泛應用。作為底層的網(wǎng)絡庫(如:memcached、Vomit、Nylon、Netchat等)
亮點
- 事件驅(qū)動
- 高性能
- 輕量級
- 專注于網(wǎng)絡
- 沒有 ACE 那么臃腫龐大
- 源代碼相當精煉、易讀
- 跨平臺
- 支持 Windows、Linux、*BSD、Mac Os
- 支持多種 I/O 多路復用技術(epoll、poll、dev/poll、select、kqueue等)
- 支持 I/O?
- 定時器和信號事件
- 注冊事件優(yōu)先級
安裝 Memcached
上傳 memcached-1.5.1.tar.gz 至服務器
解壓
[root@memcache1 ~]# tar zxvf memcached-1.5.1.tar.gz
進入
[root@memcache1 ~]# cd memcached-1.5.1
配置路徑
[root@memcache1 memcached-1.5.1]# ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent//退出
[root@memcache1 memcached-1.5.1]# cd
上傳 memcached.service?腳本至服務器
下載 psmisc
[root@memcache1 ~]# yum -y install psmisc
- psmisc 提供了 killall 命令
?添加執(zhí)行權
[root@memcache1 ~]# chmod +x memcached_service.sh
啟動服務
[root@memcache1 ~]# ./memcached_service.sh start
查看進程
[root@memcache1 ~]# netstat -anpt | grep memcached
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 20564/memcached
tcp6 0 0 :::11211 :::* LISTEN 20564/memcached
Memcached API 客戶端
先安裝 gcc*
[root@memcached-api]# yum -y install gcc*
設置好?yum 源
[root@memcached-api ~]# rm -rf /etc/yum.repos.d/*
curl -o /etc/yum.repos.d/CentOS-Base.repo ftp://192.168.2.149/repo/CentOS-Base.repo
curl -o /etc/yum.repos.d/epel.repo ftp://192.168.2.149/repo/epel.repo
[root@memcached-api ~]# yum clean all
安裝 httpd、php
[root@memcached-api ~]# yum -y install httpd mariadb mariadb-server php php-devel php-mysql
啟動服務
[root@memcached-api ~]# systemctl start mariadb
數(shù)據(jù)庫設置密碼
[root@memcached-api ~]# mysqladmin -uroot password 'pwd123'
啟動 httpd
[root@memcached-api ~]# systemctl start httpd
關閉防火墻、內(nèi)核機制
[root@memcached-api ~]# systemctl stop firewalld
[root@memcached-api ~]# setenforce 0
切換目錄
[root@memcached-api ~]# cd /var/www/html
編寫測試文件
[root@memcache-api html]# vim test1.php
<?php
phpinfo();
?>
瀏覽器訪問 192.168.10.103/test1.php
退出當前目錄
上傳 libmemcached-1.0.18.tar.gz 至服務器
解壓
[root@memcached-api ~]# tar zxvf libmemcached-1.0.18.tar.gz
進入
[root@memcached-api ~]# cd libmemcached-1.0.18
配置安裝路徑
[root@memcached-api libmemcached-1.0.18]# ./configure --prefix=/usr/local/libmemcached --with-memcached=/usr/local/memcached
make install 執(zhí)行
root@memcached-api libmemcached-1.0.18]# make && make install
退出當前目錄
上傳 memcached-2.2.0.tgz 至服務器
解壓
[root@memcached-api ~]# tar zxvf memcached-2.2.0.tgz
進入
[root@memcached-api ~]# cd memcached-2.2.0
利用 phpize 生產(chǎn)腳本
[root@memcached-api memcached-2.2.0]# phpize
安裝 zlib
[root@memcached-api memcached-2.2.0]# yum -y install zlib
指定配置腳本位置
[root@memcached-api memcached-2.2.0]#./configure --with-php-config=/usr/bin/php-config --with-libmemcached-dir=/usr/local/libmemcached/ --disable-memcachedsasl --with-zlib-dir
make install 執(zhí)行
[root@memcached-api memcached-2.2.0]# make && make install
退出當前目錄
修改配置文件
[root@memcached-api ~]# vim /etc/php.ini
//添加下面內(nèi)容
extension=memcached.so
重啟 httpd
[root@memcached-api ~]# systemctl restart httpd
瀏覽器刷新網(wǎng)站查看
切換目錄
[root@memcached-api ~]# cd /var/www/html/
上傳 test2.php代碼至服務器
?刷新網(wǎng)站測試
Memcached 數(shù)據(jù)庫操作與管理
安裝 telnet 軟件包
[root@memcachel ~]# yum -y install telnet
連接
[root@memcachel ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get key
VALUE key 3932160 25
Memcache test successful!
END
quit
root@memcachel ~]# telnet 127.0.0.1 11211
//添加一條鍵值數(shù)據(jù)
add username 0 0 8
zhangsan
STORED
-
表示鍵值名為 username
-
標記位表示自定義信息為 0
-
過期時間為 0(永不過期,單位為秒)
-
字節(jié)數(shù)為 8
-
?zhangsan?為值,這里需要注意輸入長度為8?字節(jié),與設定值符合
//查詢鍵值數(shù)據(jù)
get username
VALUE username 0 8
zhangsan
END
gets username
VALUE username 0 8 2
zhangsan
END
-
get 后跟鍵名。如果檢查最近是否更新,可以使用 gets,最后一位顯示的是更新因子,每更新一次更新因子數(shù)會加一
//更新一條鍵值數(shù)據(jù)
set username 0 0 4
lisi
STORED
get username
VALUE username 0 4
everything
END gets username
VALUE username 0 4 4
lisi
END
//清除一條緩存數(shù)據(jù)
delete username
DELETED
get username
END
//檢查后更新 check and set
add username 0 0 8
zhangsan
STOREDgets username
VALUE username 0 8 7
zhangsan
END //注意,因為更新因子和gets得到的不一致,這個語句的更新會失敗
cas username 0 0 8 1
lodging
EXISTS cas username 0 0 8 7
zhangsai
STORED
gets username
VALUE username 0 7 8
lodging
END
-
cas命令的最后一個數(shù)字是更新因子,如果gets獲取到的更新因子和cas命令提供的更新因子一致,則更新改數(shù)據(jù),否則不會更新,會提示exists
-
cas命令的第三個數(shù)字是要更新的數(shù)據(jù)的字節(jié)數(shù),和接下來輸入進去的字符串的字節(jié)數(shù)要一致,否則會報錯
//追加數(shù)據(jù)
//后追加 8 字節(jié)
append username 0 0 8
zhangsan
STORED
get username
VALUE username 0 14
lodgingzhangsan
END
//清除所有緩存數(shù)據(jù)
flush_all
OK
//查看服務器統(tǒng)計信息
stats
//返回所有鍵值對統(tǒng)計信息
stats items
//返回指定存儲空間的鍵值對
stats cachedump 1 0
//顯示各個 slab 的信息,包括 chunk 的大小、數(shù)目、使用情況等
stats slabs
//輸出所有 item 的大小和個數(shù)
stats sizes
//清空統(tǒng)計數(shù)據(jù)
stats reset
//退出
quit
案例二
Memcached 實現(xiàn)主主復制和高可用的方式
Memcached 主主復制架構
-
支持多個 Memcached 之間相互復制(雙向復制,主備都是可讀可寫的)
-
可以解決 Memcached 的容災問題
(此步驟在兩臺memcache服務器上都執(zhí)行)
- 192.168.10.101
- 192.168.10.102
修改主機名
[root@localhost ~]# hostnamectl set-hostname memcache1
[root@localhost ~]# bash
[root@localhost ~]# hostnamectl set-hostname memcache2
[root@localhost ~]# bash
這里開啟會話同步
首先關閉防火墻、內(nèi)核機制
[root@memcache1 ~]# systemctl stop firewalld
[root@memcache1 ~]# setenforce 0
安裝 gcc* 環(huán)境
[root@memcache1 ~]# yum -y install gcc*
上傳 libevent-2.1.8-stable.tar.gz 至服務器
解壓
[root@memcache1 ~]# tar zxvf libevent-2.1.8-stable.tar.gz
進入
[root@memcache1 ~]# cd libevent-2.1.8-stable
配置文件路徑
[root@memcache1 libevent-2.1.8-stable]# ./configure --prefix=/usr/local/libevent
make install 執(zhí)行
[root@memcache1 libevent-2.1.8-stable]# make && make install
上傳 memcached-1.2.8-repcached-2.2.tar.gz
解壓
[root@memcache1 ~]# tar zxvf memcached-1.2.8-repcached-2.2.tar.gz
進入
[root@memcache1 ~]# cd memcached-1.2.8-repcached-2.2
配置文件路徑
[root@Memcached1 memcached-1.2.8-repcached-2.2]# ./configure --prefix=/usr/local/memcached_replication --enable-replication --with-libevent=/usr/local/libevent
修改源代碼配置文件
[root@memcache1 memcached-1.2.8-repcached-2.2]# vim memcached.c
//找到如下幾行(在55行--60行):
/* FreeBSD 4.x doesn't have IOV_MAX exposed. */
#ifndef IOV_MAX
#if defined(__FreeBSD__) || defined(__APPLE__)
# define IOV_MAX 1024
#endif
#endif//修改成如下所示:(刪掉上面紅色的兩行)
/* FreeBSD 4.x doesn't have IOV_MAX exposed. */
#ifndef IOV_MAX
# define IOV_MAX 1024
#endif
make install 執(zhí)行
[root@memcache1 memcached-1.2.8-repcached-2.2]# make && make install
函數(shù)路徑鏈接
[root@memcache1 ~]# ln -s /usr/local/libevent/lib/libevent-2.1.so.6 /usr/lib64/
這里取消會話同步
啟動服務
[root@Memcached1 ~]# /usr/local/memcached_replication/bin/memcached -d -u root -m 128 -x 192.168.10.101
兩臺服務器查看進程
[root@memcache1 ~]# netstat -antp |grep memcached
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 52646memcached
tcp 0 0 192.168.10.101:11212 192.168.10.102:38298 ESTABLISHED 52646memcached
tcp6 0 0 :::11211 :::* LISTEN 52646memcached
[root@memcache2 ~]# netstat -antp |grep memcached
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 29976memcached
tcp 0 0 192.168.10.102:38298 192.168.10.101:11212 ESTABLISHED 29976memcached
tcp6 0 0 :::11211 :::* LISTEN 29976memcached
使用 telnet 進行簡單驗證復制功能
安裝 telnet
[root@memcache1 ~]# yum -y install telnet
在 Memcached1 上插入一條具有特點的鍵值
[root@memcache1 ~]# telnet 192.168.10.102 11211
//自定義信息+永不過期+8個字節(jié)
set username 0 0 8
12345678
STORED
get username
VALUE username 0 8
12345678
END
quit
在 Memcached2 上進行查看剛剛插入的鍵值
安裝 telnet
[root@memcache1 ~]# yum -y install telnet
[root@memcache2 ~]# telnet 192.168.10.102 11211
get username
VALUE username 0 8
12345678
END
gets username
//1代表更新因子
VALUE username 0 8 1
12345678
END
//自定義信息+永不過期+8個字節(jié)+更新因子(要與gets得到的一致)
cas username 0 0 8 1
zhangsan
STORED
這里同步會話
Memcached 主主復制+Keepalived 高可用架構
安裝配置 keepalived(兩臺主機都安裝)
[root@memcache1 ~]# yum -y install keepalived
修改主 keepalived 配置文件
[root@memcache1 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {notification_email {acassen@firewall.locfailover@firewall.locsysadmin@firewall.loc}notification_email_from Alexandre.Cassen@firewall.locsmtp_server 192.168.200.1smtp_connect_timeout 30router_id LVS_01vrrp_skip_check_adv_addr#vrrp_strictvrrp_garp_interval 0vrrp_gna_interval 0
}//定義要執(zhí)行的腳本
vrrp_script check_down {
//腳本路徑和名稱
script "/etc/keepalived/memcached.sh"
//間隔1秒執(zhí)行一次
interval 1
}vrrp_instance VI_1 {//master角色不能設置nopreempt,所以此處要設置為BACKUPstate BACKUPinterface ens33virtual_router_id 51//從主機的優(yōu)先級要小于此數(shù)字priority 100
advert_int 1
//添加,此語句關閉了搶占功能,從主機不需要
nopreemptauthentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.10.100
}//調(diào)用前面的腳本
track_script {check_down
}
}
vrrp_strict:嚴格遵守VRRP協(xié)議,禁止以下狀況
-
無VIP地址
-
配置了單播鄰居
-
在VRRP版本2中有IPv6地址,開啟動此項會自動開啟iptables防火墻規(guī)則,建議關閉此項配置
編寫腳本文件
[root@memcached1 keepalived]# vim /etc/keepalived/memcached.sh
#!/bin/bash
if [ $(ps -C memcached --no-header | wc -l) -eq 0 ]; thensystemctl stop keepalived
fi
添加執(zhí)行權限
[root@memcached1 keepalived]# chmod +x /etc/keepalived/memcached.sh
配置從 keepalived 文件
[root@memcache2 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {notification_email {acassen@firewall.locfailover@firewall.locsysadmin@firewall.loc}notification_email_from Alexandre.Cassen@firewall.locsmtp_server 192.168.200.1smtp_connect_timeout 30router_id LVS_02vrrp_skip_check_adv_addr#vrrp_strictvrrp_garp_interval 0vrrp_gna_interval 0
}//定義要執(zhí)行的腳本
vrrp_script check_down {
//腳本路徑和名稱
script "/etc/keepalived/memcached.sh"
//間隔1秒執(zhí)行一次
interval 1
}vrrp_instance VI_1 {state BACKUP interface ens33virtual_router_id 51//從主機的優(yōu)先級要小于此數(shù)字priority 99
advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.10.100
}//調(diào)用前面的腳本
track_script {check_down
}
}
編寫腳本文件
[root@memcached2 keepalived]# vim /etc/keepalived/memcached.sh
#!/bin/bash
if [ $(ps -C memcached --no-header | wc -l) -eq 0 ]; thensystemctl stop keepalived
fi
添加執(zhí)行權限
[root@memcached2 keepalived]# chmod +x /etc/keepalived/memcached.sh
vrrp_strict #嚴格遵守VRRP協(xié)vim議
這將禁止VIPs unicast peers (虛擬IP單播對等體),這樣會使得這個VIP無法進行單播通信
兩臺服務器關閉 NetworkManager
[root@memcachel keepalived]# systemctl stop NetworkManager
測試驗證
兩臺服務器上啟動 keepalived
[root@Memcached1 ~]# systemctl start keepalived
[root@memcached2 ~]# systemctl start keepalived
主服務器查看 VIP
[root@memcachel keepalived]# ip a
2:ens33: <BROADCAST,MULTICAST,UP,LOWER UP> mtu 1500 gdisc pfifo fast stateoup default glen 1000inet 192.168.10.100/32 scope global ens33
在客戶端修改緩存服務器地址
切換目錄
[root@memcached-api ~]# cd /var/www/html
[root@memcached-api html]# vim /usr/local/httpd/htdocs/test2.php
<?php
$memcache = new Memcached();
$memcache->addServer('192.168.10.100', 11211);
$memcache->set('key', 'Memcache test01 successful!', 0, 60);
$result = $memcache->get('key');
unset($memcache);
echo $result;
?>
瀏覽器刷新測試
pkill memcached
檢查當前主機的memceched進程和keepalived進程
關閉memcached后,該主機的keepalived也會被腳本關閉,于是VIP就漂移到了另一臺主機,待此主機修好后,把memcached和keepalived開啟,由于設置了不搶占,VIP不會搶占回來,但是把第二臺主機的memcached關閉后,第二臺主機的keepalived也會關閉,于是VIP就漂移回了第一臺主機。完成故障的轉移
小阿軒yx-高性能內(nèi)存對象緩存