使用Atlas完成MySQL的读写分离

使用Atlas完成MySQL的读写分离

微信搜索 zze_coding 或扫描 👉 二维码关注我的微信公众号获取更多资源推送:

介绍

Atlas 是由 Qihoo 360,Web 平台部基础架构团队开发维护的一个基于 MySQL 协议的数据中间层项目。
它是在 mysql-proxy 0.8.2 版本的基础上,对其进行了优化,增加了一些新的功能特性。
360 内部使用 Atlas 运行的 mysql 业务,每天承载的读写请求数达几十亿条。

下载地址:https://github.com/Qihoo360/Atlas/releases

环境准备

准备如下主机:

主机名IP描述
A10.0.1.200主库
B10.0.1.201从库
C10.0.1.202读写分离代理

参考「MySQL 的主从、主主复制」使用 A、B 主机搭建主从环境。

注意:

  1. Atlas 只能安装运行在 64 位的系统上;
  2. Centos 5 安装 Atlas-XX.el5.x86_64.rpm,Centos 6 安装 Atlas-XX.el6.x86_64.rpm
  3. 后端 MySQL 版本应大于 5.1,建议使用 Mysql 5.6 以上;

安装配置 Atlas

1、在 C 主机安装 Altla:

$ yum localinstall Atlas-2.2.1.el6.x86_64.rpm -y

2、备份原有配置文件:

$ cd /usr/local/mysql-proxy/conf/
$ mv test.cnf{,.bak}

3、由于 Altla 是国人研发,其配置文件说明都是中文,如下:

$ cat test.cnf.bak 
[mysql-proxy]

#带#号的为非必需的配置项目

#管理接口的用户名
admin-username = user

#管理接口的密码
admin-password = pwd

#Atlas后端连接的MySQL主库的IP和端口,可设置多项,用逗号分隔
proxy-backend-addresses = 127.0.0.1:3306

#Atlas后端连接的MySQL从库的IP和端口,@后面的数字代表权重,用来作负载均衡,若省略则默认为1,可设置多项,用逗号分隔
#proxy-read-only-backend-addresses = 127.0.0.1:3305@1

#用户名与其对应的加密过的MySQL密码,密码使用PREFIX/bin目录下的加密程序encrypt加密,下行的user1和user2为示例,将其替换为你的MySQL的用户名和加密密码!
pwds = user1:+jKsgB3YAG8=, user2:GS+tr4TPgqc=

#设置Atlas的运行方式,设为true时为守护进程方式,设为false时为前台方式,一般开发调试时设为false,线上运行时设为true,true后面不能有空格。
daemon = true

#设置Atlas的运行方式,设为true时Atlas会启动两个进程,一个为monitor,一个为worker,monitor在worker意外退出后会自动将其重启,设为false时只有worker,没有monitor,一般开发调试时设为false,线上运行时设为true,true后面不能有空格。
keepalive = true

#工作线程数,对Atlas的性能有很大影响,可根据情况适当设置
event-threads = 8

#日志级别,分为message、warning、critical、error、debug五个级别
log-level = message

#日志存放的路径
log-path = /usr/local/mysql-proxy/log

#SQL日志的开关,可设置为OFF、ON、REALTIME,OFF代表不记录SQL日志,ON代表记录SQL日志,REALTIME代表记录SQL日志且实时写入磁盘,默认为OFF
#sql-log = OFF

#慢日志输出设置。当设置了该参数时,则日志只输出执行时间超过sql-log-slow(单位:ms)的日志记录。不设置该参数则输出全部日志。
#sql-log-slow = 10

#实例名称,用于同一台机器上多个Atlas实例间的区分
#instance = test

#Atlas监听的工作接口IP和端口
proxy-address = 0.0.0.0:1234

#Atlas监听的管理接口IP和端口
admin-address = 0.0.0.0:2345

#分表设置,此例中person为库名,mt为表名,id为分表字段,3为子表数量,可设置多项,以逗号分隔,若不分表则不需要设置该项
#tables = person.mt.id.3

#默认字符集,设置该项后客户端不再需要执行SET NAMES语句
#charset = utf8

#允许连接Atlas的客户端的IP,可以是精确IP,也可以是IP段,以逗号分隔,若不设置该项则允许所有IP连接,否则只允许列表中的IP连接
#client-ips = 127.0.0.1, 192.168.1

#Atlas前面挂接的LVS的物理网卡的IP(注意不是虚IP),若有LVS且设置了client-ips则此项必须设置,否则可以不设置
#lvs-ips = 192.168.1.1

配置并启动

1、在主库创建用于读写分离的 MySQL 账号:

mysql> create user zze@'10.0.1.%' identified by '123';
mysql> grant all privileges on *.* to zze@'10.0.1.%';
mysql> flush privileges;

2、添加环境变量:

$ vim /etc/profile.d/altla.sh
PATH="$PATH:/usr/local/mysql-proxy/bin"
export PATH
$ . /etc/profile.d/altla.sh

3、生成 zze@'10.0.1.%' 用户加密后的密码:

$ encrypt 123
3yb5jEku5h4=

4、编辑 Atlas 配置文件如下:

$ vim test.cnf
[mysql-proxy]
admin-username = user
admin-password = pwd
# 配置主库(写库)
proxy-backend-addresses = 10.0.1.200:3306
# 配置从库(读库),如果有多个可以 , 隔开
proxy-read-only-backend-addresses = 10.0.1.201:3306
# 配置用于读写分离使用的账号,格式为 <user>:<pwd>,如果有多个可用 , 隔开,密码是通过 Altla 的 bin 目录下的 encrypt 程序加密生成的,加密语法 encrypt <pwd>
pwds = zze:3yb5jEku5h4=
daemon = true
keepalive = true
event-threads = 8
log-level = message
log-path = /usr/local/mysql-proxy/log
sql-log=ON
# 代理地址及端口
proxy-address = 0.0.0.0:33060
# 管理地址及端口
admin-address = 0.0.0.0:2345
charset=utf8

5、启动 Altla 服务:

# test 为 /usr/local/mysql-proxy/conf 目录下去除后缀后的配置文件名称
$ mysql-proxyd test start

Atlas 功能测试

1、使用 MySQL 客户端登入 Atlas 代理服务:

$ mysql -uzze -p123  -h 10.0.1.202 -P 33060
...
mysql>

2、测试读操作目标是否是从库:

mysql> select @@server_id;
+-------------+
| @@server_id |
+-------------+
|           2 |
+-------------+
1 row in set (0.00 sec)
-- server_id=2 的库为从库

3、测试写操作目标是否是主库:

mysql> begin; select @@server_id; commit;
Query OK, 0 rows affected (0.00 sec)

+-------------+
| @@server_id |
+-------------+
|           1 |
+-------------+
1 row in set (0.01 sec)

Query OK, 0 rows affected (0.00 sec)
-- 只要手动开启事务执行的操作,MySQL 都认为是写操作。
-- 可以看到,对于写操作,Atlas 给我们的查询请求调度到了主库。

建议:

  • DDL 建议不要使用 Atlas 触发,而是直接到主库触发(Online DDL 或者 PT-OSC);
  • DML 建议手动开启并提交/回滚事务,如 begin; DML; commit

Atlas 的管理操作

1、以配置文件中的账号通过管理地址及端口登入:

$ mysql -uuser -ppwd -h 10.0.1.202 -P2345
...
mysql> 

2、获取操作帮助:

mysql> select * from help;
+----------------------------+---------------------------------------------------------+
| command                    | description                                             |
+----------------------------+---------------------------------------------------------+
| SELECT * FROM help         | shows this help                                         |
| SELECT * FROM backends     | lists the backends and their state                      |
| SET OFFLINE $backend_id    | offline backend server, $backend_id is backend_ndx's id |
| SET ONLINE $backend_id     | online backend server, ...                              |
| ADD MASTER $backend        | example: "add master 127.0.0.1:3306", ...               |
| ADD SLAVE $backend         | example: "add slave 127.0.0.1:3306", ...                |
| REMOVE BACKEND $backend_id | example: "remove backend 1", ...                        |
| SELECT * FROM clients      | lists the clients                                       |
| ADD CLIENT $client         | example: "add client 192.168.1.2", ...                  |
| REMOVE CLIENT $client      | example: "remove client 192.168.1.2", ...               |
| SELECT * FROM pwds         | lists the pwds                                          |
| ADD PWD $pwd               | example: "add pwd user:raw_password", ...               |
| ADD ENPWD $pwd             | example: "add enpwd user:encrypted_password", ...       |
| REMOVE PWD $pwd            | example: "remove pwd user", ...                         |
| SAVE CONFIG                | save the backends to config file                        |
| SELECT VERSION             | display the version of Atlas                            |
+----------------------------+---------------------------------------------------------+
16 rows in set (0.00 sec)

该帮助说明很清晰了,下面随便演示几项操作。

3、查看代理的所有节点:

mysql> select * from backends;
+-------------+-----------------+-------+------+
| backend_ndx | address         | state | type |
+-------------+-----------------+-------+------+
|           1 | 10.0.1.200:3306 | up    | rw   |
|           2 | 10.0.1.201:3306 | up    | ro   |
+-------------+-----------------+-------+------+
2 rows in set (0.00 sec)

4、手动上下线指定节点:

-- 下线节点节点
mysql> set OFFLINE 1;
mysql> select * from backends;
+-------------+-----------------+---------+------+
| backend_ndx | address         | state   | type |
+-------------+-----------------+---------+------+
|           1 | 10.0.1.200:3306 | offline | rw   |
|           2 | 10.0.1.201:3306 | up      | ro   |
+-------------+-----------------+---------+------+
2 rows in set (0.00 sec)
-- 上线指定节点
mysql> set online 1;
+-------------+-----------------+---------+------+
| backend_ndx | address         | state   | type |
+-------------+-----------------+---------+------+
|           1 | 10.0.1.200:3306 | unknown | rw   |
+-------------+-----------------+---------+------+
1 row in set (0.00 sec)

mysql> select * from backends;
+-------------+-----------------+-------+------+
| backend_ndx | address         | state | type |
+-------------+-----------------+-------+------+
|           1 | 10.0.1.200:3306 | up    | rw   |
|           2 | 10.0.1.201:3306 | up    | ro   |
+-------------+-----------------+-------+------+
2 rows in set (0.00 sec)

5、删除及添加节点:

-- 删除指定节点
mysql> remove backend 2;
Empty set (0.00 sec)

mysql> select * from backends;
+-------------+-----------------+-------+------+
| backend_ndx | address         | state | type |
+-------------+-----------------+-------+------+
|           1 | 10.0.1.200:3306 | up    | rw   |
+-------------+-----------------+-------+------+
1 row in set (0.00 sec)
-- 添加节点
mysql> ADD SLAVE  10.0.1.201:3306;
Empty set (0.00 sec)

mysql> select * from backends;
+-------------+-----------------+-------+------+
| backend_ndx | address         | state | type |
+-------------+-----------------+-------+------+
|           1 | 10.0.1.200:3306 | up    | rw   |
|           2 | 10.0.1.201:3306 | up    | ro   |
+-------------+-----------------+-------+------+
2 rows in set (0.00 sec)

6、用户管理:

-- 首先在主库创建要添加的用户
mysql> grant all on *.* to zze1@'10.0.1.%' identified by '123';
-- 查看当前的用户
mysql> select * from pwds;
+----------+--------------+
| username | password     |
+----------+--------------+
| zze      | 3yb5jEku5h4= |
+----------+--------------+
1 row in set (0.00 sec)
-- 添加用户,前提是在主库已经有对应用户
mysql> add pwd zze1:123;
Empty set (0.00 sec)

7、持久保存到配置文件:

mysql> save config;

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://www.zze.xyz/archives/mysql-atlas.html

Buy me a cup of coffee ☕.