高性能内存对象缓存Memcached
Memcached 是一套开源的高性能分布式内存对象缓存系统,它将所有的数据都存储在内存中,因为内存中会统一维护一张巨大的 Hash 表,所以支持任意存储类型的数据。很多网站使用 Memcached 提高网站的访问速度,尤其是需要频繁访问数据的大型网站。
Memcached 是典型的 C/S 架构,因此需要构建 Memcached 服务器端与 Memcached API 客户端。Memcached 服务器端是用 C 语言编写的,而 Memcached API 客户端可用任何语言来编 写,如 PHP、Python、Perl 等,并通过 Memcached 协议与 Memcached 服务器端进行通信。 常用典型架构如下图所示:
当 Web 客户端发出请求到 Web 服务器的应用程序时,应用程序会调用 Memcached API 客户端程序库接口去连接 Memcached 服务器查询数据。如果 Web 客户端所请求的数据在 Memcached 服务端中已经缓存,则 Memcached 服务端会将数据返回给 Web 客户端;否则,会 将 Web 客户端请求发送至 MySQL 数据库,由数据库查询并返回请求的数据给 Memcached 以及 Web 客户端,与此同时 Memcached 服务器也会将数据进行保存,方便下次用户请求使用。
为何要使用Memcached,官方也给出了原因,主要是针对内存的使用:
一. Memcached核心概念
1.1 数据存储方式与数据过期方式
Memcached 具有独特的数据存储方式和数据过期方式。
数据存储方式:Slab Allocation
Slab Allocation即按组分配内存,每次先分配一个Slab,相当于一个大小为1M的页。然后,在 1M的空间里根据数据划分大小相同的Chunk。该方法可以有效解决内存碎片问题,但也可能会使内存空间产生浪费。
数据过期方式:LRU、Laxzy Expiration
LRU 和 Laxzy Expiration 是数据过期的两种方式:
- LRU(最近最少使用):是指追加的数据空间不足时,会根据LRU的情况淘汰最近最少使用的记录;
- Laxzy Expiration:即惰性过期,是指使用get时查看记录时间,从而检查记录是否已经过期。
1.2 Memcached 缓存机制
缓存是常驻在内存的数据,能够快速进行读取,而 Memcached 就是这样一款非常出色的缓存软件。当程序写入缓存数据请求时,Memcached 的 API 接口将 Key 输入路由算法模块路由到集群中一台服务,之后由 API 接口与服务器进行通信,完成一次分布式缓存写入。
1.3 Memcached 分布式
Memcached 分布式部署主要依赖于Memcached的客户来端实现,多个Memcached 服务器是独立的。分布式数据如何存储是由路由算法所决定。当数据到达客户端程序库,客户端的算法就依据路由算法来决定保存的 Memcached 服务器。读取数据时,客户端依据使用保存数据时相同的路由算法选中和存储数据时相同的服务器来读取数据。
1.4 Memcached 路由算法
求余数hash算法
求余数hash算法先用key做hash运算得到一个整数,再去做hash算法,根据 余数进行路由,这种算法适合大多数据需求。但是不适合用在动态变化的环境中,比如有大有量机器添加或者删除,这样会导致大量的对象存储位置失效。
一致性hash算法
一致性hash算法适合在动态变化的环境中使用。原理是按照hash算法把对应的 key通过一定的hash算法处理后映射形成一个首尾相接闭合循环,然后通过使用与对象存储一样的hash算法将机器也映射到环中,顺时针方向计算将所有对象存储到离自己最近的机器中。
二. 案例实施
本案例使用三台CentOS 7.7系统完成,其中:两台是Memcached服务器,另一台是基于LAMP架构进行 Memcached扩展的Memcached API客户端,具体需根据企业需求进行架构调整。
主机名 | IP地址 | 主要软件 |
---|---|---|
memcached01 | 192.168.154.101 | memcached-1.5.22 libevent-2.1.11 magent-0.5 Keepalived v1.3.5 |
memcached02 | 192.168.154.102 | memcached-1.5.22 libevent-2.1.11 magent-0.5 Keepalived v1.3.5 |
web-server | 192.168.154.100 | httpd-2.4.6 php-7.2.27 memcached-3.0.4 libmemcached-1.0.16 |
2.1 安装Memcached服务器
2.1.1 基本环境配置
- IP地址配置
- 主机名设置
- 关闭Selinux
2.1.2 安装 Libevent
Libevent是一款跨平台的事件处理接口的封装,可以兼容多个操作系统的事件访问。Memcached的安装依赖于Libevent,因此需要先完成Libevent的安装。
#下载并解压
[root@memcached01 ~]# wget -c https://github.com/libevent/libevent/releases/download/release-2.1.11-stable/libevent-2.1.11-stable.tar.gz
[root@memcached01 ~]# tar zxvf libevent-2.1.11-stable.tar.gz -C /usr/src/
[root@memcached01 ~]# cd /usr/src/libevent-2.1.11-stable/
#进行编译安装
[root@memcached01 libevent-2.1.11-stable]# ./configure --prefix=/usr/local/libevent
[root@memcached01 libevent-2.1.11-stable]# make
[root@memcached01 libevent-2.1.11-stable]# make install
2.1.3 安装 Memcached
#下载最新版本
[root@memcached01 ~]# wget -c https://www.memcached.org/files/memcached-1.5.22.tar.gz
#解压缩
[root@memcached01 ~]# tar zxvf memcached-1.5.22.tar.gz -C /usr/src/
#安装
[root@memcached01 ~]# cd /usr/src/memcached-1.5.22/
[root@memcached01 ~]# ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent/
[root@memcached01 ~]# make
[root@memcached01 ~]# make install
2.1.4 设置 Memcached 服务脚本
Memcached 服务器安装完成后,可以使用安装目录下的 bin/memcached 来启动服务。但是,为了更加方便的管理 Memcached,编写脚本来管理 Memcached 服务。
#准备工作
[root@memcached01 ~]# groupadd -g 990 memcached
[root@memcached01 ~]# useradd -u 990 -g memcached -s /sbin/nologin memcached
[root@memcached01 ~]# vim /etc/sysconfig/memcached
PORT="11211" #监听端口
USER="memcached" #启动服务的用户
MAXCONN="1024" #最大连接数
CACHESIZE="512" #分配的内存大小
OPTIONS=""
#编写systemd的unit文件
[root@memcached01 ~]# vim /usr/lib/systemd/system/memcached.service
[Unit]
Description=Memcached
Before=httpd.service
After=network.target
[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/memcached
ExecStart=/usr/local/memcached/bin/memcached -u $USER -p $PORT -m $CACHESIZE -c $MAXCONN $OPTIONS
[Install]
WantedBy=multi-user.target
2.1.5 启动服务,并放行端口
[root@memcached01 ~]# systemctl daemon-reload
[root@memcached01 ~]# systemctl enable memcached.service
[root@memcached01 ~]# systemctl start memcached.service
[root@memcached01 ~]# systemctl status memcached.service
● memcached.service - Memcached
Loaded: loaded (/usr/lib/systemd/system/memcached.service; disabled; vendor preset: disabled)
Active: active (running) since 一 2020-02-03 11:34:12 CST; 6s ago
Main PID: 3382 (memcached)
CGroup: /system.slice/memcached.service
└─3382 /usr/local/memcached/bin/memcached -u memcached -p 11211 -m 512 -c 1024
2月 03 11:34:12 memcached02 systemd[1]: Started Memcached.
#查看端口并放行
[root@memcached01 ~]# netstat -antp | grep memcached
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 3382/memcached
tcp6 0 0 :::11211 :::* LISTEN 3382/memcached
[root@memcached01 ~]# firewall-cmd --add-port=11211/tcp --permanent
success
[root@memcached01 ~]# firewall-cmd --reload
success
2.2 Memcached API 客户端
为了使得程序可以直接调用 Memcached 库和接口,可以使用 Memcached 扩展组件将 Memcache 添加为 PHP 的一个模块。此扩展使用了 Libmemcached 库提供的 API 与 Memcached 服务端进行交互。
2.2.1 安装LAMP环境
安装Apache网站服务
[root@web-server ~]# yum install httpd -y
[root@web-server ~]# systemctl enable httpd.service
[root@web-server ~]# systemctl start httpd.service
[root@web-server ~]# firewall-cmd --add-service=http --permanent
[root@web-server ~]# firewall-cmd --add-service=https --permanent
[root@web-server ~]# firewall-cmd --reload
安装mysql数据库
#安装mysql数据库
[root@web-server ~]# wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
[root@web-server ~]# rpm -ivh mysql80-community-release-el7-3.noarch.rpm
[root@web-server ~]# yum install mysql-community-server -y
#启动数据库并开机启动
[root@web-server ~]# systemctl enable mysqld.service
[root@web-server ~]# systemctl start mysqld.service
#设置root用户新密码
[root@web-server ~]# grep 'temporary password' /var/log/mysqld.log
2019-05-25T03:30:25.989353Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: gw2yrdVKWy,g
[root@web-server ~]#mysql -u root -pgw2yrdVKWy,g
#进入数据库后更改密码
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass4!';
#注意:MySQL的 validate_password 插件默认安装。这将要求密码包含至少一个大写字母,一个小写字母,一个数字和一个特殊字符,并且密码总长度至少为8个字符。
#防火墙放行MySQL服务
[root@web-server ~][root@web-server ~]# firewall-cmd --add-service=mysql --permanent
[root@web-server ~]# firewall-cmd --reload
安装PHP
安装PHP源
[root@web-server ~]# rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
[root@web-server ~]# rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
安装PHP7.2
[root@web-server ~]# yum install php72w php72w-cli php72w-common php72w-gd php72w-ldap php72w-mbstring php72w-mcrypt php72w-mysql php72w-pdo
安装pecl-memcached API 组件
root@web-server html]# yum install php72w-pecl-memcached -y
建立测试网页文件
[root@web-server html]# pwd
/var/www/html
[root@web-server html]# vim index.php
<?php
phpinfo();
?>
#重启Apache服务
[root@web-server html]# systemctl restart httpd.service
测试访问
使用浏览器进行访问,看到memcached模块,说明已经添加成功。
2.2.2 测试 Memcached-API 功能
通过编写简单的 PHP 测试代码调用 Memcache 程序接口来测试是否与 Memcached 服务器协同工作,代码如下:
[root@web-server html]# vim /var/www/html/test.php
<?php
$memcache = new Memcached();
$memcache->addServer('192.168.154.101',11211);
$memcache->set('key','Memcache test successful!');
$result = $memcache->get('key');
unset($memcache);
echo $result;
?>
此段代码的作用是在客户端连接 Memcached 服务器,设置名为‘key’的键的值为 ‘Memcache test successful!’,并读取显示,成功表示服务器与客户端协同工作正常,使 用浏览器进行访问,测试结果如图所示。
三. Memcached 数据库操作与管理
Memcache 协议简单可直接使用 telnet 连接 Memcached 的 11211 端口对 Memcached 数据库进行操作与管理。
[root@web-server html]# telnet 127.0.0.1 11211
Trying 192.168.154.101...
Connected to 192.168.154.101.
Escape character is '^]'.
#输入操作命令即可
操作命令格式:
<command name> <key> <flags> <exptime> <bytes>\r\n<data block>\r\n
#参数说明如下:
command set/add/replace/delete等操作命令
key key用于查找缓存值
flags 可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息
expiration 在缓存中保存键值对的时间长度(以秒为单位,0 表示永远)
bytes 在缓存中存储的字节数
data block 存储的值(始终位于第二行)
下面是 Memcached 数据库的常见操作指令:
3.1 set
set 命令用于向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。
set userId 0 0 5
12345
STORED #服务器返回信息
#如果使用 set 命令正确设定了键值对,服务器将使用单词 STORED 进行响应。本示例向缓存中添加了一个键值对,
#其键为userId,其值为12345。并将过期时间设置为 0,这将向 memcached 通知您希望将此值存储在缓存中直到删除它为止。
3.2 add
仅当缓存中不存在键时,add命令才会向缓存中添加一个键值对。如果缓存中已经存在键,则之前的值将仍然保持相同,并且您将获得响应 NOT_STORED。
add userId 0 0 5
55555
NOT_STORED #已经存在,返回消息
add companyId 0 0 3
564
STORED #键不存在,服务器返回成功
3.3 replace
仅当键已经存在时,replace命令才会替换缓存中的键。如果缓存中不存在键,那么您将从 memcached 服务器接受到一条 NOT_STORED 响应。
replace accountId 0 0 5
67890
NOT_STORED #键不存在,所以不能更新
set accountId 0 0 5
67890
STORED
replace accountId 0 0 5
55555
STORED #键存在了,可以更新了
3.4 get
get命令用于检索与之前添加的键值对相关的值,您将使用get执行大多数检索操作。
get userId
VALUE userId 0 5
12345
END
get companyId
VALUE companyId 0 3
564
END
get username
END
#get命令相当简单,只需使用一个键来调用get,如果这个键存在于缓存中,则返回相应的值。如果不存在,则不返回任何内容。
3.5 delete
delete 命令用于删除memcached中的任何现有值。您将使用一个键调用delete,如果该键存在于缓存中,则删除该值。如果不存在,则返回一条NOT_FOUND 消息。
delete userId
DELETED #成功删除
delete username
NOT_FOUND #无法删除不存在的键值
get userId
END
3.6 gets
gets命令的功能类似于基本的get命令。两个命令之间的差异在于,gets返回的信息稍微多一些:64位的整型值,非常像名称/值对的“版本”标识符。
set userId 0 0 5
12345
STORED
get userId
VALUE userId 0 5
12345
END
gets userId
VALUE userId 0 5 5
12345
END
考虑get和gets命令之间的差异。gets命令将返回一个额外的值:在本例中是整型值5,用于标识名称/值对。如果对此名称/值对执行另一个set命令,则gets返回的额外值将会发生更改,以表明名称/值对已经被更新。
set userId 0 0 5
33333
STORED
gets userId
VALUE userId 0 5 6
33333
END
#可以看到gets返回的值已经更新为6,,每次修改名称/值对时,该值都会发生更改。
3.7 cas
cas(check 和 set)是一个非常便捷的memcached命令,用于设置名称/值对的值(如果该名称/值对在您上次执行gets后没有更新过)。它使用与set命令相类似的语法,但包括一个额外的值:gets返回的额外值。
gets userId
VALUE userId 0 5 6 #额外值为6
33333
END
cas userId 0 0 5 6 #使用额外值6
88888
STORED
# 执行成功
gets userId
VALUE userId 0 5 8 #额外值为8
66666
END
set userId 0 0 5 #中间修改过键值
55555
STORED
gets userId
VALUE userId 0 5 9 #新的额外值为9
55555
END
cas userId 0 0 5 8 #使用以前的额外值8
77777
EXISTS #出现失败返回值
#注意,cas并未使用gets最近返回的整型值,所以返回EXISTS值以示失败。
#从本质上说,同时使用gets和cas命令可以防止您使用自上次读取后经过更新的键值对。
3.8 append和prepend
append将数据追加到当前缓存数据后面,当缓存数据存在时才存储;prepend 将数据追加到当前缓存数据的之前,当缓存数据存在时才存储。
set username 0 0 7
Michael
STORED
get username
VALUE username 0 7
Michael
END
append username 0 0 7
_Jordan
STORED
get username
VALUE username 0 14
Michael_Jordan
END
#在键名username原键值前追加数据使用prepend命令
prepend username 0 0 3
001
STORED
gets username
VALUE username 0 17 13
001Michael_Jordan
END
3.9 服务器状态信息查看
stats
stats命令显示了关于当前memcached实例的信息:
STAT pid 1139 #进程ID
STAT uptime 4820 #服务器运行秒数
STAT time 1580739313 #服务器当前Unix时间戳
STAT version 1.5.22 #服务器版本
STAT libevent 2.0.21-stable #libevent版本
STAT pointer_size 64 #操作系统字大小(这台服务器是64位的)
STAT rusage_user 0.373755 #该进程累计的用户时间,单位:秒
STAT rusage_system 0.537273 #该进程累计的系统时间,单位:秒
STAT max_connections 1024 #最大连接数
STAT curr_connections 2 #当前打开连接数
STAT total_connections #运行以来接受的连接总数
STAT rejected_connections 2 #拒绝的连接数
STAT connection_structures 3 #Memcached分配的连接结构数量
STAT reserved_fds 20
STAT cmd_get 18 #执行get命令总数
STAT cmd_set 17
STAT cmd_flush 0
STAT cmd_touch 0
STAT cmd_meta 0
STAT get_hits 15 #get命中次数
STAT get_misses 3 #get未命中次数
STAT get_expired 0
STAT get_flushed 0
STAT delete_misses 1
STAT delete_hits 1
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 1
STAT cas_badval 1
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 762 #读取字节总数
STAT bytes_written 712 #写入字节总数
STAT limit_maxbytes 536870912 #分配的内存数(字节)
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT time_in_listen_disabled_us 0
STAT threads 4 #线程数
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT slab_reassign_rescues 0
STAT slab_reassign_chunk_rescues 0
STAT slab_reassign_evictions_nomem 0
STAT slab_reassign_inline_reclaim 0
STAT slab_reassign_busy_items 0
STAT slab_reassign_busy_deletes 0
STAT slab_reassign_running 0
STAT slabs_moved 0
STAT lru_crawler_running 0
STAT lru_crawler_starts 3315
STAT lru_maintainer_juggles 8423
STAT malloc_fails 0
STAT log_worker_dropped 0
STAT log_worker_written 0
STAT log_watcher_skipped 0
STAT log_watcher_sent 0
STAT bytes 298 #存储item字节数
STAT curr_items 4 #当前的item个数
STAT total_items 13 #总的item个数
STAT slab_global_page_pool 0
STAT expired_unfetched 0
STAT evicted_unfetched 0
STAT evicted_active 0
STAT evictions 0
STAT reclaimed 0
STAT crawler_reclaimed 0
STAT crawler_items_checked 18
STAT lrutail_reflocked 0
STAT moves_to_cold 13
STAT moves_to_warm 3
STAT moves_within_lru 2
STAT direct_reclaims 0
STAT lru_bumps_dropped 0
END
stats items
显示各个slab中item的数目和存储时长(最后一次访问距离现在的秒数)。
STAT items:1:number 4
STAT items:1:number_hot 0
STAT items:1:number_warm 0
STAT items:1:number_cold 4
STAT items:1:age_hot 0
STAT items:1:age_warm 0
STAT items:1:age 4498
STAT items:1:mem_requested 298
STAT items:1:evicted 0
STAT items:1:evicted_nonzero 0
STAT items:1:evicted_time 0
STAT items:1:outofmemory 0
STAT items:1:tailrepairs 0
STAT items:1:reclaimed 0
STAT items:1:expired_unfetched 0
STAT items:1:evicted_unfetched 0
STAT items:1:evicted_active 0
STAT items:1:crawler_reclaimed 0
STAT items:1:crawler_items_checked 22
STAT items:1:lrutail_reflocked 0
STAT items:1:moves_to_cold 13
STAT items:1:moves_to_warm 3
STAT items:1:moves_within_lru 2
STAT items:1:direct_reclaims 0
STAT items:1:hits_to_hot 0
STAT items:1:hits_to_warm 2
STAT items:1:hits_to_cold 13
STAT items:1:hits_to_temp 0
END
stats cachedump slabs_id limit_num
- slabs_id:由stats items返回的结果(STAT items后面的数字)决定的
- limit_num:返回的记录数,0表示返回所有记录
- 通过stats items、stats cachedump slab_id limit_num 配合get命令可以遍历memcached的记录。
stats cachedump 1 0
ITEM username [17 b; 0 s]
ITEM userId [5 b; 0 s]
ITEM accountId [5 b; 0 s]
ITEM companyId [3 b; 0 s]
END
stats cachedump 1 2
ITEM username [17 b; 0 s]
ITEM userId [5 b; 0 s]
END
stats slabs
显示各个slab的信息,包括chunk的大小、数目、使用情况等。
STAT 1:chunk_size 96
STAT 1:chunks_per_page 10922
STAT 1:total_pages 1
STAT 1:total_chunks 10922
STAT 1:used_chunks 4
STAT 1:free_chunks 10918
STAT 1:free_chunks_end 0
STAT 1:get_hits 15
STAT 1:cmd_set 17
STAT 1:delete_hits 1
STAT 1:incr_hits 0
STAT 1:decr_hits 0
STAT 1:cas_hits 1
STAT 1:cas_badval 1
STAT 1:touch_hits 0
STAT active_slabs 1
STAT total_malloced 1048576
END
stats sizes
输出所有item的大小和个数。
stats reset
清空统计数据。
flush_all
清除所有缓存数据。
四. Memcached+Magent+Keepalived实现高可用群集
4.1 magent代理的用途
如果memcached其中一个缓存节点的机器down机,那么客户端存入的缓存数据将会丢失一部分,我们可以采用 Magent 缓存代理,防止单点现象,缓存代理也可以做备份,通过客户端连接到缓存代理服务器,缓存代理服务器连接缓存服务器,缓存代理服务器可以连接多台Memcached机器,这样就能实现实现高可用以及防止单点故障。
4.2 keepalived的用途
但是如果magent代理服务器宕机了,就不能继续提供服务,所以就用到了keepalived,通过keepalived配置文件设置优先级来决定谁做主magent或者从magent,当主magent正常运行时vip在主magent,当主magent宕机vip自动换到从magent,主magent恢复后vip自动回到主magent上。
4.3 安装magent
[root@memcached01 ~]# mkdir /opt/magent/
[root@memcached01 ~]# tar zxvf magent-0.5.tar.gz -C /opt/magent/
[root@memcached01 ~]# cd /opt/magent/
#编辑文件
[root@memcached01 magent]# vim ketama.h #在最开头添加如下3行内容
#ifndef SSIZE_MAX
#define SSIZE_MAX 32767
#endif
[root@memcached01 magent-0.5]# vim Makefile
LIBS = -levent -lm -L /usr/local/libevent/lib #修改这一行
INCLUDE=-I /usr/local/libevent/include #添加这一行
[root@memcached01 magent]# make
gcc -Wall -g -O2 -I/usr/local/include -m64 -o magent magent.o ketama.o /usr/lib64/libevent.a /usr/lib64/libm.a
[root@memcached01 magent]# ls
ketama.c ketama.h ketama.o magent magent.c magent.o Makefile
#为了方便使用
[root@memcached01 ~]# cp /opt/magent/magent /usr/bin/
下面是编译时的一些常见错误及解决方法
[root@memcached01 magent]# make
gcc -Wall -g -O2 -I/usr/local/include -m64 -c -o magent.o magent.c
magent.c:71:19: 致命错误:event.h:没有那个文件或目录
#include <event.h>
^
编译中断。
make: *** [magent.o] 错误 1
#解决以上错误
[root@memcached01 magent]# ln -s /usr/local/libevent/include/* /usr/local/include/
[root@memcached01 magent]# make
gcc -Wall -g -O2 -I/usr/local/include -m64 -c -o magent.o magent.c
magent.c: 在函数‘writev_list’中:
magent.c:729:17: 错误:‘SSIZE_MAX’未声明(在此函数内第一次使用)
if (toSend > SSIZE_MAX ||
^
magent.c:729:17: 附注:每个未声明的标识符在其出现的函数内只报告一次
make: *** [magent.o] 错误 1
#解决以上错误
[root@memcached01 magent]# vim ketama.h #在最开头添加如下3行内容
#ifndef SSIZE_MAX
#define SSIZE_MAX 32767
#endif
[root@memcached01 magent]# make
gcc -Wall -g -O2 -I/usr/local/include -m64 -c -o magent.o magent.c
gcc -Wall -g -O2 -I/usr/local/include -m64 -c -o ketama.o ketama.c
gcc -Wall -g -O2 -I/usr/local/include -m64 -o magent magent.o ketama.o /usr/lib64/libevent.a /usr/lib64/libm.a
gcc: 错误:/usr/lib64/libevent.a:没有那个文件或目录
gcc: 错误:/usr/lib64/libm.a:没有那个文件或目录
make: *** [magent] 错误 1
#解决以上错误
[root@memcached01 magent]# ln -s /usr/local/libevent/lib/libevent.a /usr/lib64/libevent.a
[root@memcached01 magent]# cp /usr/lib64/libm.so /usr/lib64/libm.a
4.4 magent的命令使用
[root@memcached01 ~]# magent -h
memcached agent v0.6 Build-Date: Feb 7 2020 17:38:57
Usage:
-h this message
-u uid
-g gid
-p port, default is 11211. (0 to disable tcp support)
-s ip:port, set memcached server ip and port #主memcached的IP和端口
-b ip:port, set backup memcached server ip and port #从memcached的IP和端口
-l ip, local bind ip address, default is 0.0.0.0
-n number, set max connections, default is 4096
-D don't go to background
-k use ketama key allocation algorithm
-f file, unix socket path to listen on. default is off
-i number, set max keep alive connections for one memcached server, default is 20
-v verbose
只在memcached01上启动magent
#启动magent
[root@memcached01 ~]# magent -u root -n 4096 -l 192.168.154.101 -p 12000 -s 192.168.154.101:11211 -b 192.168.154.102:11211
#查看是否启动
[root@memcached01 ~]# netstat -antp | grep magent
tcp 0 0 192.168.154.101:12000 0.0.0.0:* LISTEN 18347/magent
#防火墙放行端口12000
[root@memcached01 ~]# firewall-cmd --add-port=12000/tcp --permanent
[root@memcached01 ~]# firewall-cmd --reload
4.5 在客户端上进行测试
[root@web-server ~]# telnet 192.168.154.101 12000
Trying 192.168.154.101...
Connected to 192.168.154.101.
Escape character is '^]'.
add password 0 0 6
123456
STORED
get password
VALUE password 0 6
123456
END
quit
Connection closed by foreign host.
然后在从memcached02上检查
[root@memcached02 ~]# telnet 192.168.154.102 11211
Trying 192.168.154.102...
Connected to 192.168.154.102.
Escape character is '^]'.
get password
VALUE password 0 6
123456 #已经可以得到刚才添加的值
END
quit
Connection closed by foreign host.
4.6 停掉主节点的memcached服务,在client主机上测试
[root@memcached01 ~]# systemctl stop memcached.service
在客户端上继续操作,可以操作,现在其实操作的是从节点的memcached服务
[root@web-server ~]# telnet 192.168.154.101 12000
Trying 192.168.154.101...
Connected to 192.168.154.101.
Escape character is '^]'.
set username 0 0 10
zhangsan02
STORED
gets username
VALUE username 0 10 8
zhangsan02
END
4.7 在magent节点上安装keepalived软件,实现magent的高可用
[root@memcached01 ~]# yum install keepalived -y
从magent不需要安装magent软件,只需把主节点生成的magent命令文件 复制到从magent的/usr/bin目录下即可
[root@memcached01 ~]# scp /usr/bin/magent 192.168.154.102:/usr/bin/
4.8 在主magent上修改keepalived配置文件
[root@memcached01 ~]# 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 MAGENT_HA
##删除以下4行内容
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
##添加新脚本magent
vrrp_script magent {
script "/opt/shell/magent.sh"
interval 2
}
##修改vrrp_instance实例
vrrp_instance VI_1 {
state MASTER
interface ens32
virtual_router_id 51
priority 100
advert_int 1
##添加使用新脚本
track_script {
magent
}
authentication {
auth_type PASS
auth_pass 1111
}
##定义一个虚拟IP
virtual_ipaddress {
192.168.154.200
}
}
##下面多余的部分可以全部删除
4.9 在从magent上编辑keepalived配置文件
#从主magent上把配置脚本复制到从magent上
scp /etc/keepalived/keepalived.conf root@192.168.154.102:/etc/keepalived/keepalived.conf
[root@memcached02 ~]# vim /etc/keepalived/keepalived.conf
router_id MAGENT_HB #修改为MAGENT_HB
state BACKUP #修改为BACKUP
virtual_router_id 51 #ID必须相同
priortity 90 #优先级比主magent低
4.10 在主magent上配置 magent脚本
[root@memcached01 ~]# mkdir /opt/shell -p
[root@memcached01 ~]# vim /opt/shell/magent.sh
#!/bin/bash
K=`ps -ef| grep keepalived | grep -v grep | wc -l`
if [ $K -gt 0 ];then
magent -u root -n 51200 -l 192.168.154.200 -p 12000 -s 192.168.154.101:11211 -b 192.168.154.102:11211
else
pkill -9 magent
fi
[root@memcached01 ~]# chmod a+x /opt/shell/magent.sh
4.11 在从magent上配置 magent脚本
[root@memcached02 ~]# mkdir /opt/shell
[root@memcached02 ~]# vim /opt/shell/magent.sh
#!/bin/bash
K=`ip addr | grep 192.168.154.200 | grep -v grep | wc -l`
if [ $K -gt 0 ];then
magent -u root -n 51200 -l 192.168.154.200 -p 12000 -s 192.168.154.101:11211 -b 192.168.154.102:11211
else
pkill -9 magent
fi
[root@memcached02 ~]# chmod a+x /opt/shell/magent.sh
4.12 在主从magent上均启动keepalived服务
[root@memcached01 ~]# systemctl enable keepalived.service
[root@memcached01 ~]# systemctl restart keepalived.service
##防火墙放行vrrp协议
[root@memcached01 ~]# firewall-cmd --add-rich-rule='rule protocol value='vrrp' accept' --permanent
success
[root@memcached01 ~]# firewall-cmd --reload
然后发现主magent服务器上以及存在VIP:192.168.154.200,在客户端上访问VIP的12000端口
[root@web-server ~]# telnet 192.168.154.200 12000
Trying 192.168.154.200...
Connected to 192.168.154.200.
Escape character is '^]'.
get username
VALUE username 0 4
mary
END
set username 0 0 8
zhangsan
STORED
gets username
VALUE username 0 8 2
zhangsan
END
停止主magent的keepalived服务,VIP飘逸到从magent,客户端依然可以访问memcached服务
[root@memcached01 ~]# systemctl stop keepalived.service
[root@web-server ~]# telnet 192.168.154.200 12000
Trying 192.168.154.200...
Connected to 192.168.154.200.
Escape character is '^]'.
get username
VALUE username 0 8
zhangsan
END