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

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

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模式下

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


<think>好的,用户现在想了解数据库集群高可用性设计的相关信息和解决方案。首先,我需要回顾之前的对话,确保这次回答符合用户的需求,并且正确引用之前的资料。用户之前提到了MySQL Cluster、MMM、DRBD、MHA等方案,所以这次需要进一步详细说明这些方案,并结合用户提供的引用内容。 首先,用户给出的引用中,引用[1]提到MySQL的高可用架构设计,主从复制和集群方案。引用[3]讨论了淘宝的MySQL高可用方案,结合MHA和ProxySQL。引用[4]提到了客户端会话管理和Memcached集群。这些需要整合到回答中,确保信息的相关性和准确性。 接下来,用户的问题是关于数据库集群高可用性设计的实现方案。需要分点回答,结构清晰。可能需要从基础架构、常见方案、关键技术、实践案例等方面展开。 需要确保每个部分都包含具体的实现方案,比如主从复制、集群架构、中间件应用、数据同步机制等。同时,结合用户提供的引用,例如在讲MHA时,可以提到淘宝的案例,引用ProxySQL的使用,这样能增强回答的可信度。 另外,用户可能关心如何选择不同的方案,优缺点比较,以及实际应用中的注意事项。例如,MMM的单点故障问题,MHA的主备切换风险,这些都需要在回答中提及,并给出解决方案,如结合Keepalived或使用ProxySQL来避免VIP漂移。 还要注意技术细节,比如数据同步中的半同步复制、GTID,故障转移中的健康检查和自动切换,以及负载均衡中间件如ProxySQL和HAProxy的应用。同时,会话管理的部分需要引用用户提到的Memcached集群和magent代理,说明如何实现高可用的会话管理。 最后,需要生成相关问题,这些问题应该围绕用户可能进一步关心的点,比如方案选型、数据一致性、容器化部署的影响等,帮助用户深入理解。 确保回答符合格式要求,使用正确的中文,LaTeX格式,引用标记正确。避免使用Markdown,用自然的分段和项目符号。同时,检查是否有遗漏的用户引用,确保每个引用都被合理利用,例如引用[2]关于Nacos的集群设计可能不直接相关,但可以忽略,因为用户提到引用仅供参考,重点应放在数据库相关的内容上。</think>### 数据库集群高可用性设计实现方案 #### 一、基础架构与核心目标 高可用性(High Availability, HA)的核心是通过冗余设计降低单点故障风险,确保服务持续可用。数据库集群需满足以下目标: 1. **自动故障转移**:主节点宕机时,备节点可自动接管服务。 2. **数据一致性**:通过同步或半同步复制保证主备数据一致。 3. **负载均衡**:分散读请求压力,提升整体性能[^1]。 --- #### 二、典型实现方案 ##### 1. **主从复制架构** - **原理**:主库(Master)处理写操作,从库(Slave)异步/半同步复制数据。 - **技术实现**: - **半同步复制**:主库提交事务后需等待至少一个从库确认,平衡一致性与性能。 - **GTID(全局事务标识)**:简化主从切换流程,避免二进制日志偏移量不一致问题。 ```sql -- 配置半同步复制(主库) INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; SET GLOBAL rpl_semi_sync_master_enabled = 1; ``` ##### 2. **MHA(Master High Availability)** - **架构**:管理节点监控主库健康状态,发现故障后触发切换。 - **关键步骤**: 1. 从库通过`SHOW SLAVE STATUS`验证数据同步进度。 2. 选举数据最接近主库的从库为新主库。 3. 修改中间件(如ProxySQL)路由规则,指向新主库[^3]。 - **优化点**:结合ProxySQL替代VIP漂移,简化客户端配置[^3]。 ##### 3. **分布式集群(如MySQL Cluster)** - **NDB引擎**:数据分片存储于多个数据节点,支持并行查询。 - **适用场景**:高并发写入、低延迟要求的OLTP系统。 - **限制**:跨节点事务需协调,复杂度较高[^1]。 ##### 4. **共享存储方案(如DRBD+Heartbeat)** - **原理**:通过DRBD实现块设备级同步,Heartbeat监控服务状态。 - **配置示例**: ```bash # DRBD资源配置文件 resource mysql_res { protocol C; # 同步复制模式 disk /dev/sdb1; meta-disk internal; on node1 { address 192.168.1.10:7788; } on node2 { address 192.168.1.11:7788; } } ``` --- #### 三、关键技术组件 1. **中间件层**: - **ProxySQL**:支持读写分离、连接池管理、故障自动检测。 - **HAProxy**:基于TCP/HTTP的负载均衡,配合健康检查实现流量分发。 2. **数据同步机制**: - **组复制(Group Replication)**:基于Paxos协议的多主同步,适用于金融级一致性场景。 3. **会话管理**: - **分布式Session存储**:使用Memcached集群+magent代理,避免单点故障[^4]。 --- #### 四、实践案例分析(以电商场景为例) 1. **读写分离架构**: - 写操作路由至主库,读操作分发至多个从库。 - 通过中间件自动剔除延迟过高的从库。 2. **容灾设计**: - 同城双活+异地灾备,RPO(恢复点目标)<1分钟,RTO(恢复时间目标)<30秒。 3. **监控体系**: - Prometheus+Grafana监控QPS、复制延迟、节点状态。 - 自定义告警规则(如主从延迟>5秒触发预警)。 --- #### 五、方案选型建议 | 方案 | 一致性 | 性能 | 复杂度 | 适用场景 | |---------------|--------|-------|--------|----------------------| | 主从复制+MHA | 最终 | 高 | 中 | 中小规模OLTP | | MySQL Cluster | 强一致 | 中 | 高 | 高并发写入 | | DRBD+Heartbeat| 强一致 | 低 | 低 | 小规模关键业务 | --- ### 相关问题 1. **如何评估主从复制与组复制的性能差异?** 2. **在Kubernetes环境中部署数据库集群需要注意哪些问题?** 3. **金融级强一致性场景下,如何优化数据库集群的吞吐量?** 4. **ProxySQL与HAProxy在负载均衡设计中的优劣对比?** [^1]: 主从复制与集群方案需结合业务需求选择同步模式。 : ProxySQL可简化MHA架构的流量切换逻辑。 [^4]: Memcached集群需配合magent实现高可用会话存储。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值