高性能内存对象缓存Memcached原理与部署

案例概述

Memcached概述

  • 一套开源的高性能分布式内存对象缓存系统
  • 所有的数据都存储在内存中
  • 支持任意存储类型的数据
  • 提高网站的访问速度

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

  • 数据存储方式:Slab Allocation
    • 按组分配内存,每次分配一个Slab,相当于一个大小为1M的页,然后再1M的空间里根据数据划分大小相同的Chunk
  • 数据过期方式
    • LRU:数据空间不足时,会根据LRU的情况淘汰最近最少使用的记录
    • Lazy Expiration:惰性过期,是指使用get时查看记录时间,从而检查记录是否已经过期

Memcached缓存机制

  • 当程序写入缓存数据请求时,Memcached的API接口将Key输入路由算法模块路由到集群中的一台服务器,之后API接口与服务器进行通信,完成一次分布式缓存写入

Memcached分布式

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

  • 当数据到达客户端程序库,客户端的算法就依据路由算法来决定保存的Memcached 服务器。读取数据时,客户端依据使用保存数据时相同的路由算法选中和存储数据时相同的服务器来读取数据

Memcached路由算法

  • 求余数hash算法
    • 先用key做hash运算得到一个整数,再做hash算法,根据余数进行路由
    • 适合大多数数据需求,但是不适合用在动态变化的环境中
  • 一致性hash算法
    • 按照hash算法吧对应key通过一定的hash算法处理后映射行程一个首尾相接闭合循环,然后通过使用与对象存储一样的hash算法将机器也映射到环中,顺时针方向计算将所有对象存储到自己最近的机器中
    • 适合在动态变化的环境中国使用

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:设置各节点的主机名
bash 复制代码
主机: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
bash 复制代码
[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
bash 复制代码
[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 服务脚本

bash 复制代码
[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 ~]# chmod 755 /usr/local/memcached/memcached_service.sh
[root@memcache1 ~]# /usr/local/memcached/memcached_service.sh start
[root@memcache1 ~]# netstat -anpt | grep memcached

2.3:Memcached API 客户端

设置好阿里yum源

bash 复制代码
yum -y install httpd mariadb mariadb-server php php-devel php-mysql
systemctl start mariadb
mysqladmin -u root password 'pwd123'
systemctl start httpd
1:编译安装 Libmemcached
bash 复制代码
[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是用源码包安装的,使用如下方法

bash 复制代码
[root@memcached-api ~]# tar -xzvf memcached-2.2.0.tgz 
[root@memcached-api ~]# cd memcached-2.2.0/

Yum -y install zlib-devel
[root@memcached-api memcached-2.2.0]# /usr/local/php5/bin/phpize
/usr/bin/phpize

备注:

此命令可以在memcached-2.2.0 下生成memcached的配置脚本

phpize命令需要autoconf****包的支持 **:**yum -y install autoconf

bash 复制代码
./configure \
--enable-memcached \
--with-php-config=/usr/local/php5/bin/php-config \
--with-libmemcached-dir=/usr/local/libmemcached \
--disable-memcached-sasl
bash 复制代码
[root@memcached-api memcached-2.2.0]# make 
[root@memcached-api memcached-2.2.0]# make test 
[root@memcached-api memcached-2.2.0]# make install

(2)如果lamp是用yum安装的,使用如下方法

如果是用yum安装的lamp环境,使用如下方法安装 Memcached 扩展

bash 复制代码
[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

备注:

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

备注:

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

3:配置 PHP 添加 Memcached 组件

(1)添加Memcached

bash 复制代码
[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 

备注:

如果使用的yum安装的php,

[root@memcache2 ~]# vim /etc/php.ini

去掉extension_dir=" "

只添加extension=memcached.so

启动http服务

bash 复制代码
[root@memcached-api php5]# systemctl restart httpd

(2)通过 PHPinfo 查看是否已经添加 Memcached 扩展模块

使用浏览器进行访问

4:测试 Memcached-API 功能

bash 复制代码
[root@memcached-api ~]# vim /usr/local/httpd/htdocs/test2.php

<?php 
$memcache = new Memcached(); 
$memcache->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

测试结果如下:

2.4:Memcached 数据库操作与管理
bash 复制代码
##安装telnet
[root@memcache1 ~]# yum -y install telnet
[root@memcache1 ~]# telnet 127.0.0.1 11211

1:添加一条键值数据

bash 复制代码
add username 0 0 8 
zhangsan 
STORED

备注:

表示键值名为 username,

标记位表示自定义信息为 0,

过期时间为 0(永不过期,单位为秒)

字节数为 8;

zhangsan 为值,这里需要注意输入长度为8 字节,与设定值符合

2:查询键值数据

bash 复制代码
get username 
VALUE username 0 8 
zhangsan 
END 
gets username 
VALUE username 0 8 2 
zhangsan 
END 

备注:

get 后跟键名。如果检查最近是否更新,可以使用 gets,最后一位显示的是更新因子,每更新一次更新因子数会加一

3:更新一条键值数据

bash 复制代码
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:清除一条缓存数据

bash 复制代码
delete username 
DELETED 
get username 
END

5:检查后更新 check and set

bash 复制代码
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:追加数据

bash 复制代码
append username 0 0 8 //后追加 8 字节 
zhangsan 
STORED 
get username 
VALUE username 0 14 
lodgingzhangsan 
END 

7:清除所有缓存数据

bash 复制代码
flush_all 

8:查看服务器统计信息

bash 复制代码
stats 
stats items      //返回所有键值对统计信息
stats cachedump 1 0    //返回指定存储空间的键值对 
stats slabs     //显示各个 slab 的信息,包括 chunk 的大小、数目、使用情况等 
stats sizes     //输出所有 item 的大小和个数 
stats reset     //清空统计数据

9:退出

bash 复制代码
quit

Memcached 实现主主复制和高可用的方式

3.1:Memcached 主主复制架构

Memcached 的复制功能支持多个 Memcached 之间相互复制(双向复制,主备都是可读可写的),可以解决 Memcached 的容灾问题。

1:安装带有复制功能的 Memcached

(此步骤在两台memcache服务器上都执行)

(1):安装 Libevent

bash 复制代码
[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

bash 复制代码
[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上启动

bash 复制代码
[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上启动

bash 复制代码
[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_addr> 绑定地址 (默认:所有都允许,无论内外网或者本机更换IP,有安全隐患,若设置为127.0.0.1就只能本机访问)

-P 将PID写入文件,这样可以使得后边进行快速进程终止, 需要与 -d 一起使用

(3)在两台服务器上检查进程

bash 复制代码
[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 上插入一条具有特点的键值

bash 复制代码
[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 上进行查看刚刚插入的键值

bash 复制代码
[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 上查看复制的情况

bash 复制代码
[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(两台主机都安装)
bash 复制代码
[root@memcache1 ~]# yum -y install keepalived

(1)配置主 keepalived

bash 复制代码
[root@memcache1 ~]# vim /etc/keepalived/keepalived.conf 
! Configuration File for keepalived

global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   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
}

备注:

  • vrrp_strict:严格遵守VRRP协议,禁止以下状况:1.无VIP地址 2.配置了单播邻居 3.在VRRP版本2中有IPv6地址,开启动此项会自动开启iptables防火墙规则,建议关闭此项配置
bash 复制代码
[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
bash 复制代码
[root@memcached1 keepalived]# chmod +x /etc/keepalived/memcached.sh

(2)配置从keepalived

bash 复制代码
[root@memcache2 ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   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
}

}
bash 复制代码
[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
bash 复制代码
[root@memcached2 keepalived]# chmod +x /etc/keepalived/memcached.sh

备注:

vrrp_strict #严格遵守VRRP协vim议

这将禁止VIPs unicast peers (虚拟IP单播对等体),这样会使得这个VIP无法进行单播通信

2:测试验证

(1)在两台服务器上启动keepalived

bash 复制代码
[root@Memcached1 ~]# systemctl start keepalived 
[root@memcached2 ~]# systemctl start keepalived

(2)在客户端修改缓存服务器地址

bash 复制代码
[root@memcached-api ~]# vim /usr/local/httpd/htdocs/test3.php
<?php 
$memcache = new Memcached(); 
$memcache->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)浏览器访问测试

备注:

pkill memcached

检查当前主机的memceched进程和keepalived进程,

关闭memcached后,该主机的keepalived也会被脚本关闭,于是VIP就漂移到了另一台主机,待此主机修好后,把memcached和keepalived开启,由于设置了不抢占,VIP不会抢占回来,但是把第二台主机的memcached关闭后,第二台主机的keepalived也会关闭,于是VIP就漂移回了第一台主机。完成故障的转移。

相关推荐
滴水之功26 分钟前
VMware OpenWrt怎么桥接模式联网
linux·openwrt
夏木~36 分钟前
Oracle 中什么情况下 可以使用 EXISTS 替代 IN 提高查询效率
数据库·oracle
W215539 分钟前
Liunx下MySQL:表的约束
数据库·mysql
黄名富44 分钟前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
ldinvicible44 分钟前
How to run Flutter on an Embedded Device
linux
言、雲1 小时前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
YRr YRr2 小时前
解决Ubuntu 20.04上编译OpenCV 3.2时遇到的stdlib.h缺失错误
linux·opencv·ubuntu
认真学习的小雅兰.2 小时前
如何在Ubuntu上利用Docker和Cpolar实现Excalidraw公网访问高效绘图——“cpolar内网穿透”
linux·ubuntu·docker
一个程序员_zhangzhen2 小时前
sqlserver新建用户并分配对视图的只读权限
数据库·sqlserver
zfj3212 小时前
学技术学英文:代码中的锁:悲观锁和乐观锁
数据库·乐观锁··悲观锁·竞态条件