小阿轩yx-高性能内存对象缓存
案例分析
案例概述
Memcached
- 是一款开源的高性能分布式内存对象缓存系统
 - 用于很多网站提高访问速度,尤其是需要频繁访问数据的大型网站
 - 是典型的 C/S 架构,需要构建 Memcached 服务器端与 Memcached API 客户端
 - 用 C 语言编写的,Memcached API 客户端可用任何语言来编写(如 PHP、Python、Perl等)
 

案例前置知识点
数据存储方式与数据过期方式
Memcached
- 具有独特的数据存储方式和数据过期方式
 
数据存储方式:Slab Allocation
- 按组分配内存
 

数据过期方的两种方式
- LRU
 - Laxzy Expiration
 
LRU
- 指追加的数据空间不足时,会根据 LRU 的情况淘汰最近最少使用的记录
 - 可以有效解决内存碎片问题,但也可能会使内存空间产生浪费
 
Laxzy Expiration
- 即懒惰过期,指使用 get 时查看记录时间,从而检查记录是否已经过期
 
Memcached 缓存机制
- 缓存是常驻在内存的数据,能够快速进行读取
 - 是一款非常出色的缓存软件
 

Memcached 分布式
- 部署主要依赖于 Memcached 的客户端来实现
 - 多个 Memcached 服务器是独立的
 - 数据如何存储是由路由器算法所决定
 

Memcached 路由算法
求余数 hash 算法
- 先用 key 做 hash 运算得到一个整数,再做 hash 算法,根据余数进行路由,适合大多数据需求
 - 不适合在动态变化环境中,比如大量机器添加或删除,会导致大量的对象存储位置失效
 
一致性 hash 算法
- 适合在动态变化的环境中使用
 
原理
- 按照 hash 算法把对应的 key 通过一定的 hash 算法处理后映射形成一个首尾相接闭合循环
 - 然后通过使用与对象存储一样的 hash算法将机器也映射到环中
 - 顺时针方向计算将所有对象存储到离自己最近的机器中
 

案例环境
- 使用三台 CentOS 7.9 系统完成
 - 两台是 Memcached 服务器,另一台是基于 LAMP 架构进行 Memcached 扩展的 Memcached API 客户端
 
| 主机 | 操作系统 | 主机名/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 客户端
 - 实现 Memcached 主主复制+高可用
 
案例实现思路
- 首先安装 Memcached 服务器 及Memcached APl客户端
 - 利用 Keepalived 构建 Memcached 高可用服务器架构
 - 测试并验证 Keepalived 高可用所带来的稳定性
 
案例一
单 memcached 节点缓存系统
设置各节点的主机名
主机
- 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 
首先关闭防火墙、内核机制
[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* 环境
[root@memcache1 libevent ~]# yum -y install gcc* 
配置路径前缀
[root@memcache1 libevent-2.1.8-stable]# ./configure --prefix=/usr/local/libevent 
make install 执行
[root@memcache1 libevent-2.1.8-stable]# make && make install 
Libevent
- 是用 C 语言编写
 - 轻量级
 - 开源高性能事件通知库
 - 已经被广泛应用。作为底层的网络库(如:memcached、Vomit、Nylon、Netchat等)
 
亮点
- 事件驱动
 - 高性能
 - 轻量级
 - 专注于网络
 - 没有 ACE 那么臃肿庞大
 - 源代码相当精炼、易读
 - 跨平台
 - 支持 Windows、Linux、*BSD、Mac Os
 - 支持多种 I/O 多路复用技术(epoll、poll、dev/poll、select、kqueue等)
 - 支持 I/O
 - 定时器和信号事件
 - 注册事件优先级
 
安装 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 命令
 
添加执行权
[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 
数据库设置密码
[root@memcached-api ~]# mysqladmin -uroot password 'pwd123' 
启动 httpd
[root@memcached-api ~]# systemctl start httpd 
关闭防火墙、内核机制
[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 执行
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 生产脚本
[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 执行
[root@memcached-api memcached-2.2.0]# make && make install 
退出当前目录
修改配置文件
[root@memcached-api ~]# vim /etc/php.ini
//添加下面内容
extension=memcached.so 
重启 httpd
[root@memcached-api ~]# systemctl restart httpd 
浏览器刷新网站查看

切换目录
[root@memcached-api ~]# cd /var/www/html/ 
上传 test2.php代码至服务器
刷新网站测试

Memcached 数据库操作与管理
安装 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
//添加一条键值数据
add username 0 0 8
zhangsan
STORED 
-  
表示键值名为 username
 -  
标记位表示自定义信息为 0
 -  
过期时间为 0(永不过期,单位为秒)
 -  
字节数为 8
 -  
zhangsan 为值,这里需要注意输入长度为8 字节,与设定值符合
 
//查询键值数据
get username 
VALUE username 0 8 
zhangsan 
END 
gets username 
VALUE username 0 8 2 
zhangsan 
END 
-  
get 后跟键名。如果检查最近是否更新,可以使用 gets,最后一位显示的是更新因子,每更新一次更新因子数会加一
 
//更新一条键值数据
set username 0 0 4 
lisi 
STORED 
get username 
VALUE username 0 4 
everything 
END gets username
VALUE username 0 4 4
lisi
END 
//清除一条缓存数据
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命令的最后一个数字是更新因子,如果gets获取到的更新因子和cas命令提供的更新因子一致,则更新改数据,否则不会更新,会提示exists
 -  
cas命令的第三个数字是要更新的数据的字节数,和接下来输入进去的字符串的字节数要一致,否则会报错
 
//追加数据
//后追加 8 字节 
append username 0 0 8
zhangsan 
STORED 
get username 
VALUE username 0 14 
lodgingzhangsan 
END 
//清除所有缓存数据
flush_all 
OK 
//查看服务器统计信息
stats 
//返回所有键值对统计信息
stats items
//返回指定存储空间的键值对 
stats cachedump 1 0
//显示各个 slab 的信息,包括 chunk 的大小、数目、使用情况等 
stats slabs
//输出所有 item 的大小和个数 
stats sizes
//清空统计数据
stats reset 
//退出
quit 
案例二
Memcached 实现主主复制和高可用的方式
Memcached 主主复制架构
-  
支持多个 Memcached 之间相互复制(双向复制,主备都是可读可写的)
 -  
可以解决 Memcached 的容灾问题
 
(此步骤在两台memcache服务器上都执行)
- 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 
这里开启会话同步
首先关闭防火墙、内核机制
[root@memcache1 ~]# systemctl stop firewalld
[root@memcache1 ~]# setenforce 0 
安装 gcc* 环境
[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 执行
[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 执行
[root@memcache1 memcached-1.2.8-repcached-2.2]# make && make install 
函数路径链接
[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个字节
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个字节+更新因子(要与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
}//定义要执行的脚本
vrrp_script check_down {
//脚本路径和名称
script "/etc/keepalived/memcached.sh"
//间隔1秒执行一次
interval 1
}vrrp_instance VI_1 {//master角色不能设置nopreempt,所以此处要设置为BACKUPstate BACKUPinterface ens33virtual_router_id 51//从主机的优先级要小于此数字priority 100
advert_int 1
//添加,此语句关闭了抢占功能,从主机不需要
nopreemptauthentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.10.100
}//调用前面的脚本
track_script {check_down
}
} 
vrrp_strict:严格遵守VRRP协议,禁止以下状况
-  
无VIP地址
 -  
配置了单播邻居
 -  
在VRRP版本2中有IPv6地址,开启动此项会自动开启iptables防火墙规则,建议关闭此项配置
 
编写脚本文件
[root@memcached1 keepalived]# vim /etc/keepalived/memcached.sh
#!/bin/bash
if [ $(ps -C memcached --no-header | wc -l) -eq 0 ]; thensystemctl stop keepalived
fi 
添加执行权限
[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
}//定义要执行的脚本
vrrp_script check_down {
//脚本路径和名称
script "/etc/keepalived/memcached.sh"
//间隔1秒执行一次
interval 1
}vrrp_instance VI_1 {state BACKUP      interface ens33virtual_router_id 51//从主机的优先级要小于此数字priority 99
advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.10.100
}//调用前面的脚本
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 
添加执行权限
[root@memcached2 keepalived]# chmod +x /etc/keepalived/memcached.sh 
vrrp_strict #严格遵守VRRP协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-高性能内存对象缓存