amoeba是一款开源的数据库代理中间件,能够接收客户端的数据库请求,根据预设的规则将读请求转发到从库,写请求转发到主库,从而实现mysql数据库的读写分离,降低单库的压力。本文将以amoeba 3.x版本为例,讲解完整的实现流程。
环境准备
在开始配置之前,需要先准备好以下环境:
- 已搭建完成的mysql主从复制架构,主库地址为192.168.0.10,从库地址为192.168.0.11,主从同步正常
- 一台独立的服务器安装amoeba,地址为192.168.0.12,系统为CentOS 7
- amoeba 3.x安装包,需要依赖JDK 1.8及以上环境,先完成JDK的安装配置
amoeba安装步骤
解压安装包
将下载好的amoeba安装包上传到192.168.0.12服务器,解压到指定目录:
# 解压安装包到/usr/local目录 tar -zxvf amoeba-mysql-3.0.5-RC-distribution.zip -C /usr/local/ # 重命名目录方便后续操作 mv /usr/local/amoeba-mysql-3.0.5-RC /usr/local/amoeba
配置环境变量
编辑系统环境变量文件,添加amoeba的路径:
# 编辑环境变量文件 vim /etc/profile # 在文件末尾添加以下内容 export AMOEBA_HOME=/usr/local/amoeba export PATH=$PATH:$AMOEBA_HOME/bin # 使环境变量生效 source /etc/profile
核心配置文件修改
amoeba的读写分离规则主要通过两个配置文件实现,分别是dbServers.xml和amoeba.xml。
配置dbServers.xml
该文件用于定义后端mysql数据库的连接信息和负载均衡规则,修改/usr/local/amoeba/conf/dbServers.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE amoeba:dbServers SYSTEM "dbserver.dtd">
<amoeba:dbServers xmlns:amoeba="http://amoeba.meidusa.com/">
<!-- 抽象数据库服务器配置,定义通用连接参数 -->
<dbServer name="abstractServer" abstractive="true">
<factoryConfig class="com.meidusa.amoeba.mysql.net.MysqlServerConnectionFactory">
<property name="connectionManager">${defaultManager}</property>
<property name="sendBufferSize">64</property>
<property name="receiveBufferSize">128</property>
<!-- mysql端口 -->
<property name="port">3306</property>
<!-- 后端mysql的用户名 -->
<property name="user">amoeba_user</property>
<!-- 后端mysql的密码 -->
<property name="password">amoeba_pass</property>
</factoryConfig>
<poolConfig class="com.meidusa.toolkit.common.poolable.PoolableObjectPool">
<property name="maxActive">500</property>
<property name="maxIdle">500</property>
<property name="minIdle">10</property>
<property name="minEvictableIdleTimeMillis">600000</property>
<property name="timeBetweenEvictionRunsMillis">600000</property>
<property name="testOnBorrow">true</property>
<property name="testOnReturn">true</property>
<property name="testWhileIdle">true</property>
</poolConfig>
</dbServer>
<!-- 主库配置 -->
<dbServer name="master" parent="abstractServer">
<factoryConfig>
<!-- 主库IP地址 -->
<property name="ipAddress">192.168.0.10</property>
</factoryConfig>
</dbServer>
<!-- 从库配置 -->
<dbServer name="slave" parent="abstractServer">
<factoryConfig>
<!-- 从库IP地址 -->
<property name="ipAddress">192.168.0.11</property>
</factoryConfig>
</dbServer>
<!-- 读库池配置,包含从库 -->
<dbServer name="readPool" virtual="true">
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
<property name="loadbalance">1</property>
<property name="poolNames">slave</property>
</poolConfig>
</dbServer>
</amoeba:dbServers>
配置amoeba.xml
该文件用于定义amoeba的监听端口、读写分离规则等核心参数,修改/usr/local/amoeba/conf/amoeba.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE amoeba:configuration SYSTEM "amoeba.dtd">
<amoeba:configuration xmlns:amoeba="http://amoeba.meidusa.com/">
<proxy>
<service name="Amoeba for Mysql" class="com.meidusa.amoeba.mysql.server.MySQLService">
<property name="port">8066</property>
<property name="ipAddress">0.0.0.0</property>
<property name="connectionFactory">
<bean class="com.meidusa.amoeba.mysql.net.MysqlClientConnectionFactory">
<property name="sendBufferSize">128</property>
<property name="receiveBufferSize">64</property>
</bean>
</property>
<property name="authenticateProvider">
<bean class="com.meidusa.amoeba.mysql.server.MysqlClientAuthenticator">
<!-- 客户端连接amoeba的用户名 -->
<property name="user">amoeba_client</property>
<!-- 客户端连接amoeba的密码 -->
<property name="password">client_pass</property>
<property name="filter">
<bean class="com.meidusa.amoeba.server.AuthenticateFilter">
<property name="ipAccessControl">
<bean class="com.meidusa.amoeba.server.AccessControl">
<property name="type">allow</property>
<property name="ipRange">192.168.0.0/24</property>
</bean>
</property>
</bean>
</property>
</bean>
</property>
</service>
<runtime class="com.meidusa.amoeba.mysql.context.MysqlRuntimeContext">
<property name="executeThreadSize">128</property>
<property name="connectionManager">${defaultManager}</property>
<property name="queryTimeout">60</property>
</runtime>
</proxy>
<queryRouter class="com.meidusa.amoeba.mysql.parser.MysqlQueryRouter">
<property name="ruleLoader">
<bean class="com.meidusa.amoeba.route.TableRuleFileLoader">
<property name="ruleFile">${amoeba.home}/conf/rule.xml</property>
<property name="functionFile">${amoeba.home}/conf/ruleFunctionMap.xml</property>
</bean>
</property>
<property name="sqlFunctionFile">${amoeba.home}/conf/functionMap.xml</property>
<property name="LRUMapSize">1500</property>
<!-- 默认写库为主库 -->
<property name="defaultPool">master</property>
<!-- 写库配置 -->
<property name="writePool">master</property>
<!-- 读库配置 -->
<property name="readPool">readPool</property>
</queryRouter>
</amoeba:configuration>
后端mysql权限配置
需要在主库上创建amoeba连接后端mysql的用户,并授予对应权限:
-- 登录主库mysql mysql -u root -p -- 创建amoeba连接用户,允许amoeba服务器连接 CREATE USER 'amoeba_user'@'192.168.0.12' IDENTIFIED BY 'amoeba_pass'; -- 授予所有权限 GRANT ALL PRIVILEGES ON *.* TO 'amoeba_user'@'192.168.0.12' WITH GRANT OPTION; -- 刷新权限 FLUSH PRIVILEGES;
启动amoeba并验证
启动amoeba服务
进入amoeba安装目录的bin目录,启动服务:
cd /usr/local/amoeba/bin # 启动amoeba,后台运行 ./amoeba start & # 查看启动日志,确认无报错 tail -f /usr/local/amoeba/logs/amoeba.log
如果日志中出现Amoeba for Mysql startup success的提示,说明amoeba启动成功,默认监听8066端口。
读写分离验证
使用客户端连接amoeba的8066端口,执行读写操作验证分离效果:
# 连接amoeba mysql -h 192.168.0.12 -P 8066 -u amoeba_client -p # 输入密码client_pass后进入mysql命令行
执行写操作,查看主库是否有对应数据:
-- 创建测试数据库
CREATE DATABASE test_db;
USE test_db;
-- 创建测试表
CREATE TABLE test_table(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20));
-- 插入数据,写请求应该转发到主库
INSERT INTO test_table(name) VALUES('test_data');
登录主库查看数据是否存在:
mysql -h 192.168.0.10 -u root -p USE test_db; SELECT * FROM test_table;
如果主库中存在插入的数据,说明写请求转发正常。执行读操作,查看从库是否有同步的数据:
-- 在amoeba连接的命令行中执行读请求 SELECT * FROM test_table;
登录从库查看数据是否同步,同时可以在amoeba的日志中看到读请求转发到从库的记录,说明读写分离配置成功。
注意事项
- 修改配置文件后需要重启amoeba才能生效
- 如果amoeba启动失败,优先查看logs目录下的日志文件,定位连接异常、权限不足等问题
- 主从同步延迟过高时,可能会出现读请求获取到旧数据的情况,需要根据业务场景调整主从同步策略
- 生产环境中建议为amoeba配置高可用方案,避免单点故障