支付網(wǎng)站建設(shè)費/正規(guī)的培訓(xùn)學(xué)校
小阿軒yx-高性能內(nèi)存對象緩存
案例分析
案例概述
Memcached
- 是一款開源的高性能分布式內(nèi)存對象緩存系統(tǒng)
- 用于很多網(wǎng)站提高訪問速度,尤其是需要頻繁訪問數(shù)據(jù)的大型網(wǎng)站
- 是典型的 C/S 架構(gòu),需要構(gòu)建 Memcached 服務(wù)器端與 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 緩存機(jī)制
- 緩存是常駐在內(nèi)存的數(shù)據(jù),能夠快速進(jìn)行讀取
- 是一款非常出色的緩存軟件
Memcached 分布式
- 部署主要依賴于 Memcached 的客戶端來實現(xiàn)
- 多個?Memcached 服務(wù)器是獨立的
- 數(shù)據(jù)如何存儲是由路由器算法所決定
Memcached 路由算法
求余數(shù) hash 算法
- 先用 key 做 hash 運算得到一個整數(shù),再做 hash 算法,根據(jù)余數(shù)進(jìn)行路由,適合大多數(shù)據(jù)需求
- 不適合在動態(tài)變化環(huán)境中,比如大量機(jī)器添加或刪除,會導(dǎo)致大量的對象存儲位置失效
一致性 hash 算法
- 適合在動態(tài)變化的環(huán)境中使用
原理
- 按照 hash 算法把對應(yīng)的 key 通過一定的 hash 算法處理后映射形成一個首尾相接閉合循環(huán)
- 然后通過使用與對象存儲一樣的 hash算法將機(jī)器也映射到環(huán)中
- 順時針方向計算將所有對象存儲到離自己最近的機(jī)器中
案例環(huán)境
- 使用三臺 CentOS 7.9 系統(tǒng)完成
- 兩臺是 Memcached 服務(wù)器,另一臺是基于 LAMP 架構(gòu)進(jìn)行 Memcached 擴(kuò)展的 Memcached API 客戶端
主機(jī) | 操作系統(tǒng) | 主機(jī)名/IP地址 | 主要軟件及版本 |
服務(wù)器 | CentOS7.9 | Memcache1/192.168.10.101 | libevent-2.1.8-stable.tar.gz |
服務(wù)器 | 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 |
案例拓?fù)?/span>
案例需求
- 安裝部署 Memcached 服務(wù)
- 安裝 Memcached API 客戶端
- 實現(xiàn) Memcached 主主復(fù)制+高可用
案例實現(xiàn)思路
- 首先安裝 Memcached 服務(wù)器 及Memcached APl客戶端
- 利用 Keepalived 構(gòu)建 Memcached 高可用服務(wù)器架構(gòu)
- 測試并驗證 Keepalived 高可用所帶來的穩(wěn)定性
案例一
單 memcached 節(jié)點緩存系統(tǒng)
設(shè)置各節(jié)點的主機(jī)名
主機(jī)
- 192.168.10.101
[root@localhost ~]# hostnamectl set-hostname memcache1
[root@localhost ~]# bash
主機(jī)
- 192.168.10.102
[root@localhost ~]# hostnamectl set-hostname memcache2
[root@localhost ~]# bash
主機(jī)
- 192.168.10.103
[root@localhost ~]# hostnamectl set-hostname memcached-API
[root@localhost ~]# bash
安裝 Memcached 服務(wù)器
修改兩臺主機(jī)名
[root@localhost ~]# hostnamectl set-hostname memcache1
[root@localhost ~]# bash
[root@localhost ~]# hostnamectl set-hostname memcache2
[root@localhost ~]# bash
首先關(guān)閉防火墻、內(nèi)核機(jī)制
[root@memcache1 ~]# systemctl stop firewalld
[root@memcache1 ~]# setenforce 0
安裝?Libevent
上傳 libevent 包至服務(wù)器
解壓
[root@memcache1 ~]# tar zxvf libevent-2.1.8-stable.tar.gz
進(jìn)入?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)被廣泛應(yīng)用。作為底層的網(wǎng)絡(luò)庫(如:memcached、Vomit、Nylon、Netchat等)
亮點
- 事件驅(qū)動
- 高性能
- 輕量級
- 專注于網(wǎng)絡(luò)
- 沒有 ACE 那么臃腫龐大
- 源代碼相當(dāng)精煉、易讀
- 跨平臺
- 支持 Windows、Linux、*BSD、Mac Os
- 支持多種 I/O 多路復(fù)用技術(shù)(epoll、poll、dev/poll、select、kqueue等)
- 支持 I/O?
- 定時器和信號事件
- 注冊事件優(yōu)先級
安裝 Memcached
上傳 memcached-1.5.1.tar.gz 至服務(wù)器
解壓
[root@memcache1 ~]# tar zxvf memcached-1.5.1.tar.gz
進(jìn)入
[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?腳本至服務(wù)器
下載 psmisc
[root@memcache1 ~]# yum -y install psmisc
- psmisc 提供了 killall 命令
?添加執(zhí)行權(quán)
[root@memcache1 ~]# chmod +x memcached_service.sh
啟動服務(wù)
[root@memcache1 ~]# ./memcached_service.sh start
查看進(jìn)程
[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*
設(shè)置好?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
啟動服務(wù)
[root@memcached-api ~]# systemctl start mariadb
數(shù)據(jù)庫設(shè)置密碼
[root@memcached-api ~]# mysqladmin -uroot password 'pwd123'
啟動 httpd
[root@memcached-api ~]# systemctl start httpd
關(guān)閉防火墻、內(nèi)核機(jī)制
[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
退出當(dāng)前目錄
上傳 libmemcached-1.0.18.tar.gz 至服務(wù)器
解壓
[root@memcached-api ~]# tar zxvf libmemcached-1.0.18.tar.gz
進(jìn)入
[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
退出當(dāng)前目錄
上傳 memcached-2.2.0.tgz 至服務(wù)器
解壓
[root@memcached-api ~]# tar zxvf memcached-2.2.0.tgz
進(jìn)入
[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
退出當(dāng)前目錄
修改配置文件
[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ù)器
?刷新網(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
-
標(biāo)記位表示自定義信息為 0
-
過期時間為 0(永不過期,單位為秒)
-
字節(jié)數(shù)為 8
-
?zhangsan?為值,這里需要注意輸入長度為8?字節(jié),與設(shè)定值符合
//查詢鍵值數(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ù),和接下來輸入進(jìn)去的字符串的字節(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
//查看服務(wù)器統(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)主主復(fù)制和高可用的方式
Memcached 主主復(fù)制架構(gòu)
-
支持多個 Memcached 之間相互復(fù)制(雙向復(fù)制,主備都是可讀可寫的)
-
可以解決 Memcached 的容災(zāi)問題
(此步驟在兩臺memcache服務(wù)器上都執(zhí)行)
- 192.168.10.101
- 192.168.10.102
修改主機(jī)名
[root@localhost ~]# hostnamectl set-hostname memcache1
[root@localhost ~]# bash
[root@localhost ~]# hostnamectl set-hostname memcache2
[root@localhost ~]# bash
這里開啟會話同步
首先關(guān)閉防火墻、內(nèi)核機(jī)制
[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 至服務(wù)器
解壓
[root@memcache1 ~]# tar zxvf libevent-2.1.8-stable.tar.gz
進(jìn)入
[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
進(jìn)入
[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/
這里取消會話同步
啟動服務(wù)
[root@Memcached1 ~]# /usr/local/memcached_replication/bin/memcached -d -u root -m 128 -x 192.168.10.101
兩臺服務(wù)器查看進(jìn)程
[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 進(jìn)行簡單驗證復(fù)制功能
安裝 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 上進(jìn)行查看剛剛插入的鍵值
安裝 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 主主復(fù)制+Keepalived 高可用架構(gòu)
安裝配置 keepalived(兩臺主機(jī)都安裝)
[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角色不能設(shè)置nopreempt,所以此處要設(shè)置為BACKUPstate BACKUPinterface ens33virtual_router_id 51//從主機(jī)的優(yōu)先級要小于此數(shù)字priority 100
advert_int 1
//添加,此語句關(guān)閉了搶占功能,從主機(jī)不需要
nopreemptauthentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.10.100
}//調(diào)用前面的腳本
track_script {check_down
}
}
vrrp_strict:嚴(yán)格遵守VRRP協(xié)議,禁止以下狀況
-
無VIP地址
-
配置了單播鄰居
-
在VRRP版本2中有IPv6地址,開啟動此項會自動開啟iptables防火墻規(guī)則,建議關(guān)閉此項配置
編寫腳本文件
[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í)行權(quán)限
[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//從主機(jī)的優(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í)行權(quán)限
[root@memcached2 keepalived]# chmod +x /etc/keepalived/memcached.sh
vrrp_strict #嚴(yán)格遵守VRRP協(xié)vim議
這將禁止VIPs unicast peers (虛擬IP單播對等體),這樣會使得這個VIP無法進(jìn)行單播通信
兩臺服務(wù)器關(guān)閉 NetworkManager
[root@memcachel keepalived]# systemctl stop NetworkManager
測試驗證
兩臺服務(wù)器上啟動 keepalived
[root@Memcached1 ~]# systemctl start keepalived
[root@memcached2 ~]# systemctl start keepalived
主服務(wù)器查看 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
在客戶端修改緩存服務(wù)器地址
切換目錄
[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
檢查當(dāng)前主機(jī)的memceched進(jìn)程和keepalived進(jìn)程
關(guān)閉memcached后,該主機(jī)的keepalived也會被腳本關(guān)閉,于是VIP就漂移到了另一臺主機(jī),待此主機(jī)修好后,把memcached和keepalived開啟,由于設(shè)置了不搶占,VIP不會搶占回來,但是把第二臺主機(jī)的memcached關(guān)閉后,第二臺主機(jī)的keepalived也會關(guān)閉,于是VIP就漂移回了第一臺主機(jī)。完成故障的轉(zhuǎn)移
小阿軒yx-高性能內(nèi)存對象緩存