Memcached 集群的高可用(HA)架构

本文介绍如何利用magent实现在Memcache上的集群部署,包括整体架构设计、HA测试过程及结果分析,同时提出了解决memcache重启后数据丢失的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Memcache自身并没有实现集群功能,如果想用Memcahce实现集群需要借助第三方软件或者自己设计编程实现,这里将采用memagent代理实现,memagent又名magent,大家注意下,不要将这二者当成两种工具。至于memcache、magent的安装请参考文章 在Linux上安装Memcached服务 和  magent编译安装及常见错误       

整体架构

直接上图:


从图中可以看到有两个magent节点,两个memcached节点,每个magent节点又分别代理两个memcached节点,应用系统端使用magent pool来调用memcache进行存储。硬件结构为两台linux服务器,每台服务器上分别安装magent和memcached服务,并设为开机启动。这样做的好处是任何一台服务器宕机后都不影响magent pool获取memcache信息,即实现了memcached的高可用(HA),如果两台机器都宕机了,只能说明你RP太差了。当然,也可以用三台、四台或者更多服务器来提高HA。

测试HA

测试背景,本地局域网内两台服务器172.18.117.71(memcache端口11211,magent端口11210),172.18.117.113(memcache端口11211,magent端口11210),和两台服务器在同一局域网内的测试机器,下边是测试代码:

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


publicclassMainTest {publicstaticvoid main(String[] arg){
SockIOPool pool = SockIOPool.getInstance();
//magent连接池pool.setServers(new String[] { "172.18.117.71:11210","172.18.117.113:11210" });
pool.setSocketTO(3000);
pool.setNagle(false);
pool.setSocketConnectTO(0);
pool.initialize();
MemCachedClient memCachedClient = new MemCachedClient();
memCachedClient.set("becd0000", "测试例子");
//System.out.println(memCachedClient.get("becd0000"));//System.out.println(memCachedClient.flushAll());}

}

步骤1:将key为“becd0000”,value为“测试例子”通过magent的pool放到memcache中

步骤2:修改magent连接池为单个memcache连接,代码如下

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


publicclassMainTest {publicstaticvoid main(String[] arg){
SockIOPool pool = SockIOPool.getInstance();
//magent连接池pool.setServers(new String[] { "172.18.117.71:11211"});
pool.setSocketTO(3000);
pool.setNagle(false);
pool.setSocketConnectTO(0);
pool.initialize();
MemCachedClient memCachedClient = new MemCachedClient();
//memCachedClient.set("becd0000", "测试例子");System.out.println(memCachedClient.get("becd0000"));
//System.out.println(memCachedClient.flushAll());}

}

可以看到单独访问memcache是可以取到刚才所存储的值的。

步骤3:修改

pool.setServers(new String[] { "172.18.117.71:11211"});

pool.setServers(new String[] { "172.18.117.113:11211"});

再次执行可以看到和步骤2一样的结果,都可以取到值,说明通过magent代理存的值会分别放到两个memcache中

步骤4:停止172.18.117.113上的memcached服务

停止memcached服务命令:kill "cat /tmp/memcached.pid"

步骤5:再次通过magent代理取值,代码如下:

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


publicclassMainTest {publicstaticvoid main(String[] arg){
SockIOPool pool = SockIOPool.getInstance();
//magent连接池pool.setServers(new String[] { "172.18.117.71:11210","172.18.117.113:11210" });
pool.setSocketTO(3000);
pool.setNagle(false);
pool.setSocketConnectTO(0);
pool.initialize();
MemCachedClient memCachedClient = new MemCachedClient();
//memCachedClient.set("becd0000", "测试例子");System.out.println(memCachedClient.get("becd0000"));
//System.out.println(memCachedClient.flushAll());}

}

可以看到依然能够取到值。

步骤6:启动刚才停掉的memcached服务,重启后memcache中所有信息将清空

步骤7:再次通过magent代理池去取key为“becd0000”的值,代码如下:

import com.danga.MemCached.MemCachedClient;
import com.danga.MemCached.SockIOPool;


publicclassMainTest {publicstaticvoid main(String[] arg){
SockIOPool pool = SockIOPool.getInstance();
//magent连接池pool.setServers(new String[] { "172.18.117.71:11210","172.18.117.113:11210" });
pool.setSocketTO(3000);
pool.setNagle(false);
pool.setSocketConnectTO(0);
pool.initialize();
MemCachedClient memCachedClient = new MemCachedClient();
//memCachedClient.set("becd0000", "测试例子");System.out.println(memCachedClient.get("becd0000"));
//System.out.println(memCachedClient.flushAll());}

}

可以看到这里取到的值为null。

结果分析

通过以上测试可以得出结论

1、通过magent的连接池放的值会分别存在magent代理的所有memcached上去

2、如果有一个memcached宕机通过magent代理方式还能取到值

3、如果memcached修复重启后通过magent代理方式取到的值就会为Null,这是由于memcache重启后里边的值随着memcache服务的停止就消失了(因为在内存中),但是magent是通过key进行哈希计算分配到某台机器上的,memcache重启后会还从这台机器上取值,所有取到的值就没空。

解决办法

1、在每次memcache宕机修复后可以写一个程序把集群中的其他memcache的所有信息全给拷贝到当前宕机修复后的memcache中。

2、自己写代理,当从一个memcached服务上取到的值为null时再去其他memcached上取值

注意事项

magent的调用方式同memcached一样,客户端可以不用改代码即可实现切换到magent模式下

版权所有,转载请注明作者、出处。


### 构建企业级 KVS 与 Keepalived 高可用架构 #### 设计原则 为了确保键值存储 (KVS)高可用性和可靠性,在设计阶段应考虑多个因素,包括但不限于数据冗余、自动故障转移以及负载均衡。通过引入 Keepalived 来管理虚拟 IP 地址(VIP),可以有效地提高服务的连续性和响应速度[^1]。 #### 组件介绍 - **Redis 或 Memcached**: 这些是常见的分布式内存对象缓存系统,能够作为高效的 KVS 使用。 - **Keepalived**: 提供基于 VRRP 协议的心跳检测机制和服务健康状态监控功能,用于实现 VIP 的动态迁移。 #### 方案概述 采用主备模式部署两台服务器节点 A 和 B,其中一台被指定为主节点而另一台则处于热备份状态。当主节点发生故障时,Keepalived 能够迅速感知并触发切换操作,使备用节点接管业务流量继续提供服务[^2]。 #### 安装配置指南 ##### Redis/Memcached 设置 对于 Redis 或者 Memcached 的安装不再赘述,重点在于调整其配置文件以支持持久化选项(AOF/RDB),从而保障数据安全;另外还需要开启集群特性以便于横向扩展能力[^3]。 ```bash # 修改 redis.conf 中的相关参数 appendonly yes # 开启 AOF 持久化 cluster-enabled yes # 启用 Cluster 功能 ``` ##### Keepalived 安装与初始化 确保所有参与 HA 对的设计机器都已正确安装了 Keepalived 并进行了基础设置: ```bash sudo apt-get install keepalived # Debian/Ubuntu 下安装命令 yum install keepalived # CentOS/Fedora 下安装命令 ``` 接着编辑 `/etc/keepalived/keepalived.conf` 文件来定义具体的 LVS/VRRP 规则集,下面是一个简单的例子说明如何为上述提到的服务创建一个浮动 IP: ```plaintext vrrp_instance VI_1 { state MASTER !<-- 如果当前主机是 master 则设为MASTER,否则SLAVE interface eth0 !<-- 网卡名称 virtual_router_id 51 !<-- VRID 值范围(0~255),同一组内的成员需相同 priority 100 !<-- 主机优先级越高越容易成为master advert_int 1 authentication { !<-- 认证部分可选配但建议启用增加安全性 auth_type PASS auth_pass mypassword } virtual_ipaddress { !<-- 浮动ip地址列表 192.168.1.100 !<-- 此处填写实际使用的VIP } } ``` 请注意以上只是非常基本的例子,具体环境下的配置可能还会涉及到更多细节上的考量,比如网络拓扑结构的影响等[^4]。 #### 故障处理策略 除了依靠 Keepalived 自身提供的监测手段外,还可以结合外部工具如 Nagios/Zabbix 实施更全面的状态跟踪和预警通知体系。一旦发现异常情况立即采取措施恢复生产环境正常运作[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值