高性能内存对象缓存Memcached

一、案列分析

1.1案例概述

Memcached 是一套开源的高性能分布式内存对象缓存系统,它将所有的数据都存储在内存中,因为内存中会统一维护一张巨大的 Hash 表,所以支持任意存储类型的数据。很多网站使用emcached 提高网站的访问速度,尤其是需要频繁访问数据的大型网站。

Memcached 是典型的 C/S 架构,因此需要构建 Memcached 服务器端与 MemcachedAPI客户端。Memcached 服务器端是用 C 语言编写的,而 Memcached API 客户端可用任何语言来编写(如 PHP、Python、Perl 等),并通过 Memcached 协议与 Memcached 服务器端进行通信。

1.2案例前置知识点

1.数据存储方式与数据过期方式

(1)数据存储方式:Slab Allocation

Slab Allocation 即按组分配内存,每次先分配一个 Slab,相当于一个大小为 1M的页。然后,在 1M 的空间里根据数据划分大小相同的 Chunk,该方法可以有效解决内存碎片问题,但也可能会使内存空间产生浪费。

(2)数据过期方式:LRU、Laxzy Expiration

LUR 是指追加的数据空间不足时,会根据 LRU 的情况淘汰最近最少使用的记录。

Laxzy Expiration 即惰性过期,是指使用 get 时查看记录时间,从而检查记录是否已经过期。

2.Memcached 缓存机制

缓存是常驻在内存的数据,能够快速进行读取,而 Memcached 就是这样一款非常出色的缓存软件。当程序写入缓存数据请求时,Memcached 的 API 接口将 Key 输入路由算法模块并路由到集群中的一台服务器,之后由 API 接口与服务器进行通信,完成一次分布式缓存写入。

3.Memcached 分布式

Memcached分布式部署主要依赖于Memcached的客户来端实现,多个Memcached 服务器是独立的。分布式数据如何存储是由路由算法所决定。当数据到达客户端程序库,客户端的算法就依据路由算法来决定保的Memcached 服务器。读取数据时,客户端依据使用保存数据时相同的路由算法选中和存储数据时相同的服务器来读取数据。

4.Memcached 路由算法

(1)求余数 hash 算法

求余数 hash 算法先用 key 做 hash 运算得到一个整数,再去做 hash 算法,根据余数进行路由,这种算法适合大多数据需求。但是不适合用在动态变化的环境中,比如有大量机器添加或者删除,这样会导致大量的对象存储位置失效。

(2)一致性 hash 算法

一致性 hash 算法适合在动态变化的环境中使用。原理是按照 hash 算法把对应的 key 通过一定的 hash 算法处理后映射形成一个首尾相接闭合循环,然后通过使用与对象存储一样的 hash算法将机器也映射到环中,顺时针方向计算将所有对象存储到离自己最近的机器中,如图2.5 所示。

1.3案例环境

1.本案列环境

|-----|-----------|------------------------------|------------------------------------------------------------------------------------------|
| 主机 | 操作系统 | 主机名/IP地址 | 主要软件及版本 |
| 服务器 | Centos7.9 | Memcache1/192.168.10.101 | libevent-2.1.8-stable.tar.gz memcached-1.5.1.tar.gz memcached-1.2.8-repcached-2.2.tar.gz |
| 服务器 | Centos7.9 | Memcache2/192.168.10.102 | libevent-2.1.8-stable.tar.gz memcached-1.2.8-repcached-2.2.tar.gz |
| 客户端 | Centos7.9 | Memcached-API/192.168.10.103 | httpd-2.4.25.tar.gz php-5.5.38.tar.gz libmemcached-1.0.18.tar.gz memcached-2.2.0.tgz |

2.案列拓扑

二、案例实施

单memcached节点缓存系统

2.1设置各节点的主机名

复制代码
主机: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

2.2安装 Memcached 服务器

1.安装 Libevent

复制代码
[root@memcache1 ~]# systemctl stop firewalld
[root@memcache1 ~]# yum -y install gcc*
[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
[root@memcache1 libevent-2.1.8-stable]# make && make install

备注:

Libevent 是一个用C语言编写的、轻量级的开源高性能事件通知库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大;源代码相当精炼、易读;跨平台,支持 Windows、 Linux、 *BSD 和 Mac Os;支持多种 I/O 多路复用技术, epoll、 poll、 dev/poll、 select 和 kqueue 等;支持 I/O,定时器和信号等事件;注册事件优先级。

Libevent 已经被广泛的应用,作为底层的网络库;比如 memcached、 Vomit、 Nylon、 Netchat等等。

2.安装 Memcached

复制代码
[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]# make && make install

3.设置 Memcached 服务脚本

复制代码
[root@memcache1 ~]# vim /usr/local/memcached/memcached_service.sh
#!/bin/bash 
CMD="/usr/local/memcached/bin/memcached" 
start(){ 
  $CMD -d -m 128 -u root
}
stop(){ 
  killall memcached;
}

ACTION=$1
  case $ACTION in
  'start')
     start;;
  'stop')
     stop;;
'restart')
     stop
     sleep 2
     start;;
*) 
     echo 'Usage:{start|stop|restart}' 
esac 

[root@memcache1 ~]# yum -y install psmisc

备注:

psmisc提供了killall命令

复制代码
[root@memcache1 ~]# chmod 755 /usr/local/memcached/memcached_service.sh

[root@memcache1 ~]# /usr/local/memcached/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  

2.3 Memcached API 客户端

注意:

客户端需要有apache和php的环境,如果有之前做的LAMP的快照,可以使用这个快照

(如果已经有此环境,安装apache和安装php可以省略)

设置好阿里yum源

复制代码
yum -y install httpd mariadb mariadb-server php php-devel php-mysql

systemctl start mariadb

mysqladmin -u root password 'pwd123'

systemctl start httpd



cat <<EOF>/var/www/html/test1.php

<?php

phpinfo();

?>

EOF

1.编译安装 Libmemcached

复制代码
[root@memcached-api ~]# systemctl stop firewalld
[root@memcached-api ~]# setenforce 0

[root@memcached-api ~]# yum -y install gcc*
[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

[root@memcached-api libmemcached-1.0.18]# make && make install

备注:

libmemcached 是一个 memcached 的库,客户端库,C 和 C++ 语言实现的客户端库,具有低内存占用率、线程安全、并提供对memcached功能的全面支持

2.编译安装 Memcached 扩展

(1)如果lamp是用源码包安装的,使用如下方法
复制代码
[root@memcached-api ~]# tar -xzvf memcached-2.2.0.tgz 
[root@memcached-api ~]# cd memcached-2.2.0/

[root@memcached-api memcached-2.2.0]# /usr/local/php5/bin/phpize

备注:
此命令可以在memcached-2.2.0下生成memcached的配置脚本
phpize命令需要autoconf包的支持 :yum -y install autoconf


[root@memcached-api memcached-2.2.0]# cp -r /usr/local/php5/include/php/ext/ ./ 
[root@memcached-api memcached-2.2.0]# ./configure \
--enable-memcached \
--with-php-config=/usr/local/php5/bin/php-config \
--with-libmemcached-dir=/usr/local/libmemcached \
--disable-memcached-sasl

[root@memcached-api memcached-2.2.0]# make 
[root@memcached-api memcached-2.2.0]# make test 
注意:
最后会提示发送邮件报告,可以选否(n) 

[root@memcached-api memcached-2.2.0]# make install
(2)如果lamp是用yum安装的,使用如下方法
复制代码
如果是用yum安装的lamp环境,使用如下方法安装 Memcached 扩展
[root@memcached-api ~]# yum -y install zlib zlib-devel
[root@memcached-api ~]# tar -xzvf memcached-2.2.0.tgz 
[root@memcached-api ~]# cd memcached-2.2.0/
[root@memcached-api memcached-2.2.0]# /usr/bin/phpize
[root@memcached-api memcached-2.2.0]# ./configure --with-php-config=/usr/bin/php-config --with-libmemcached-dir=/usr/local/libmemcached --disable-memcached-sasl --with-zlib-dir
[root@memcached-api memcached-2.2.0]# make && make install

备注:

  1. SASL全称Simple Authentication and Security Layer,是一种用来扩充C/S模式验证能力的机制。简单来说SASL是一个胶合(glue)库,通过这个库把应用层与形式多样的认证系统整合在一起。这有点类似于 PAM,但是后者是认证方式,决定什么人可以访问什么服务,而SASL是认证过程,侧重于信任建立过程,这个过程可以调用PAM来建立信任关系。在这里Memcached就是上面提到的应用层,具体的认证交给SASL库,SASL会根据相应的认证机制来完成验证功能。

备注:

如果安装的是php7的版本,会报错:php_smart_str.h: No such file or directory

3.配置 PHP 添加 Memcached 组件

(1)添加 Memcached
复制代码
[root@memcached-api ~]# cd /usr/local/php5/ 
[root@memcached-api php5]# vim php.ini 
extension_dir = "/usr/local/php5/lib/php/extensions/no-debug-zts-20121212/" 
extension=memcached.so 
[root@memcached-api php5]# systemctl restart httpd

备注:

如果使用的yum安装的php,

root@memcache2 \~\]# vim /etc/php.ini 去掉extension_dir=" " 只添加extension=memcached.so ##### (2)通过 PHPinfo 查看是否已经添加 Memcached 扩展模块 使用浏览器进行访问 ![](https://i-blog.csdnimg.cn/direct/558852511be644c89536777a711cbeda.png) #### 4.****测试**** ****Memcached-API**** ****功能**** [root@memcached-api ~]# vim /usr/local/httpd/htdocs/test2.php addServer('192.168.10.101', 11211); $memcache->set('key', 'Memcache test successful!', 0, 60); $result = $memcache->get('key'); unset($memcache); echo $result; ?> 备注: 如果是用yum安装的lamp,此文件所在的目录在/var/www/html 访问测试:[http://192.168.10.103/test2.php](http://192.168.10.103/test.php "http://192.168.10.103/test2.php") ![](https://i-blog.csdnimg.cn/direct/b043bc61090e44678984d9a115c2e24e.png) ### 2.4**Memcached** **数据库操作与管理** [root@memcache1 ~]# yum -y install telnet [root@memcache1 ~]# telnet 127.0.0.1 11211 #### 1.添加一条键值数据 add username 0 0 8 zhangsan STORED 备注: 表示键值名为 username, 标记位表示自定义信息为 0, 过期时间为 0(永不过期,单位为秒) 字节数为 8; zhangsan 为值,这里需要注意输入长度为8 字节,与设定值符合 #### 2.查询键值数据 get username VALUE username 0 8 zhangsan END gets username VALUE username 0 8 2 zhangsan END 备注: get 后跟键名。如果检查最近是否更新,可以使用 gets,最后一位显示的是更新因子,每更新一次更新因子数会加一 #### 3.更新一条键值数据 set username 0 0 4 lisi STORED get username VALUE username 0 4 everything END gets username VALUE username 0 4 4 lisi END #### 4.清除一条缓存数据 delete username DELETED get username END #### 5.检查后更新 check and set add username 0 0 8 zhangsan STORED gets username VALUE username 0 8 7 zhangsan END cas username 0 0 8 1 ##注意,因为更新因子和gets得到的不一致,这个语句的更新会失败 lodging EXISTS cas username 0 0 8 7 zhangsai STORED gets username VALUE username 0 7 8 lodging END 备注: cas命令的最后一个数字是更新因子,如果gets获取到的更新因子和cas命令提供的更新因子一致,则更新改数据,否则不会更新,会提示exists cas命令的第三个数字是要更新的数据的字节数,和接下来输入进去的字符串的字节数要一致,否则会报错 #### 6.追加数据 append username 0 0 8 //后追加 8 字节 zhangsan STORED get username VALUE username 0 14 lodgingzhangsan END #### 7.清除所有缓存数据 flush_all OK #### 8.查看服务器统计信息 stats stats items //返回所有键值对统计信息 stats cachedump 1 0 //返回指定存储空间的键值对 stats slabs //显示各个 slab 的信息,包括 chunk 的大小、数目、使用情况等 stats sizes //输出所有 item 的大小和个数 stats reset //清空统计数据 #### 9.退出 quit ## 三、案列二 ### **Memcached** **实现主主复制和高可用的方式** ### **3.1** **Memcached** **主主复制架构** Memcached 的复制功能支持多个 Memcached 之间相互复制(双向复制,主备都是可读可写的),可以解决 Memcached 的容灾问题。 #### 1.**安装带有复制功能的** **Memcached** (此步骤在两台memcache服务器上都执行) ##### (1)安装 Libevent [root@memcache1 ~]# systemctl stop firewalld [root@memcache1 ~]# setenforce 0 [root@memcache1 ~]# yum -y install gcc* psmisc [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 [root@memcache1 libevent-2.1.8-stable]# make && make install ##### (2)安装memcached-1.2.8-repcached [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 [root@memcache1 memcached-1.2.8-repcached-2.2]# make && make install #### 2.****启动**** ****Memcached**** ****服务**** ##### (1)在memcache1上启动 [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.102 注意: 启动时要指向对端 -d:守护进程方式启动 -u:指定用户 -x:指定对端服务器的地址 -m:最大的内存使用单位是MB 默认是64MB ##### (2)在memcache2上启动 [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 备注: -x 对方IP -p 监听的TCP端口(默认: 11211) -U UDP监听端口 (默认: 11211, 0 时关闭) -d 以守护进程方式运行 -u 运行运行 Memcached的账户 非root用户 -m 最大的内存使用单位是MB 默认是64MB -c 软连接数量默认是1024 -v 输出警告和错误信息 -vv 打印客户端的请求和返回信息 -h 打印帮助信息 -i 打印memcached和libevent的版权信息 -l 绑定地址 (默认:所有都允许,无论内外网或者本机更换IP,有安全隐患,若设置为127.0.0.1就只能本机访问) -P 将PID写入文件,这样可以使得后边进行快速进程终止, 需要与 -d 一起使用 ##### (3)在两台服务器上检查进程 [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 #### 3.**使用** **telnet** **进行简单验证复制功能** ##### (1)在 Memcached1 上插入一条具有特点的键值 [root@memcache1 ~]# yum -y install telnet [root@memcache1 ~]# telnet 192.168.10.102 11211 set username 0 0 8 #自定义信息+永不过期+8个字节 12345678 STORED get username VALUE username 0 8 12345678 END quit ##### (2)在 Memcached2 上进行查看刚刚插入的键值 [root@memcache2 ~]# yum -y install telnet [root@memcache2 ~]# telnet 192.168.10.102 11211 get username VALUE username 0 8 12345678 END gets username VALUE username 0 8 1 #1代表更新因子, 12345678 END cas username 0 0 8 1 #自定义信息+永不过期+8个字节+更新因子(要与gets得到的一致) zhangsan STORED ##### (3)在 Memcached1 上查看复制的情况 [root@localhost ~]# telnet 192.168.10.101 11211 Trying 192.168.10.101... Connected to 192.168.10.101. Escape character is '^]'. get username VALUE username 0 8 zhangsan END ### 3.2**Memcached** **主主复制** **+Keepalived** **高可用架构** #### 1.****安装配置**** ****keepalived**** ****(两台主机都安装)**** [root@memcache1 ~]# yum -y install keepalived ##### (1)配置主 keepalived [root@memcache1 ~]# vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { [email protected] [email protected] [email protected] } notification_email_from [email protected] smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_01 vrrp_skip_check_adv_addr #vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_script check_down { ##定义要执行的脚本 script "/etc/keepalived/memcached.sh" ##脚本路径和名称 interval 1 ##间隔1秒执行一次 } vrrp_instance VI_1 { state BACKUP ##master角色不能设置nopreempt,所以此处要设置为BACKUP interface ens33 virtual_router_id 51 priority 100 ##从主机的优先级要小于此数字 advert_int 1 nopreempt ##添加,此语句关闭了抢占功能,从主机不需要 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.10.100 } track_script { ##调用前面的脚本 check_down } } [root@memcached1 keepalived]# vim /etc/keepalived/memcached.sh #!/bin/bash # if [ $(ps -C memcached --no-header | wc -l) -eq 0 ]; then systemctl stop keepalived fi [root@memcached1 keepalived]# chmod +x /etc/keepalived/memcached.sh 备注: * vrrp_strict:严格遵守VRRP协议,禁止以下状况:1.无VIP地址 2.配置了单播邻居 3.在VRRP版本2中有IPv6地址,开启动此项会自动开启iptables防火墙规则,建议关闭此项配置 ##### (2)配置从keepalived [root@memcache2 ~]# vim /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { notification_email { [email protected] [email protected] [email protected] } notification_email_from [email protected] smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_02 vrrp_skip_check_adv_addr #vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_script check_down { ##定义要执行的脚本 script "/etc/keepalived/memcached.sh" ##脚本路径和名称 interval 1 ##间隔1秒执行一次 } vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 51 priority 99 ##从主机的优先级要小于此数字 advert_int 1 authentication { auth_type PASS auth_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 ]; then systemctl stop keepalived fi [root@memcached2 keepalived]# chmod +x /etc/keepalived/memcached.sh 备注: vrrp_strict #严格遵守VRRP协vim议 这将禁止VIPs unicast peers (虚拟IP单播对等体),这样会使得这个VIP无法进行单播通信 #### 2.测试验证 ##### (1)在两台服务器上启动keepalived [root@Memcached1 ~]# systemctl start keepalived [root@memcached2 ~]# systemctl start keepalived ##### (2)在客户端修改缓存服务器地址 [root@memcached-api ~]# vim /usr/local/httpd/htdocs/test3.php addServer('192.168.10.100', 11211); $memcache->set('key', 'Memcache test successful!', 0, 60); $result = $memcache->get('key'); unset($memcache); echo $result; ?> 注意: 如果是yum安装的httpd,次此文件在/var/www/html目录下 ##### (3)浏览器访问测试 ![](https://i-blog.csdnimg.cn/direct/265711e74d2f4a898fecb0552731071f.png) 备注: pkill memcached 检查当前主机的memceched进程和keepalived进程, 关闭memcached后,该主机的keepalived也会被脚本关闭,于是VIP就漂移到了另一台主机,待此主机修好后,把memcached和keepalived开启,由于设置了不抢占,VIP不会抢占回来,但是把第二台主机的memcached关闭后,第二台主机的keepalived也会关闭,于是VIP就漂移回了第一台主机。完成故障的转移。

相关推荐
一介草民丶31 分钟前
Mysql | 主从复制的工作机制
数据库·mysql·oracle
酱学编程4 小时前
redis 延迟双删
数据库·redis·缓存
xujiangyan_6 小时前
MySQL的半同步模式
数据库·git·mysql
飞翔沫沫情6 小时前
《MySQL 5.7.44审计合规实践:插件集成与日志分割自动化方案》
数据库·mysql·mysql审计
MXsoft6186 小时前
云原生运维在 2025 年的发展蓝图
运维·服务器·数据库
不辉放弃7 小时前
SQL 主键(Primary Key)
数据库·sql·oracle
qq_339282237 小时前
PostgreSQL-常用命令
数据库·postgresql·oracle
沸材8 小时前
Redis——实现消息队列
数据库·redis·消息队列
しかし1181148 小时前
C语言队列的实现
c语言·开发语言·数据结构·数据库·经验分享·链表
⁤⁢初遇8 小时前
MySQL---数据库基础
数据库