[toc]

中间件Atlas的概述

image-20230425220023585

Atlas简介

Atlas是由 Qihoo 360公司Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。
它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础上,修改了大量bug,添加了很多功能特性。
它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基础上,修改了大量bug,添加了很多功能特性。

Atlas主要功能

  1. 读写分离
  2. 从库负载均衡
  3. IP过滤
  4. 自动分表
  5. DBA可平滑上下线DB
  6. 自动摘除宕机的DB

Atlas相对于官方MySQL-Proxy的优势

  1. 将主流程中所有Lua代码用C重写,Lua仅用于管理接口
  2. 重写网络模型、线程模型
  3. 实现了真正意义上的连接池
  4. 优化了锁机制,性能提高数十倍

Atlas的安装及配置

Atlas安装

  • 官方提供的Atlas有两种:

    • Atlas (普通) : Atlas-2.2.1.el6.x86_64.rpm
    • tlas (分表) : Atlas-sharding_1.0.1-el6.x86_64.rpm
  • 安装流程

    1
    2
    3
    4
    5
    6
    7
    # 在数据库服务器下载Atlas
    wget httpss://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm

    # 安装
    rpm -ivh Atlas-2.2.1.el6.x86_64.rpm
    Preparing... ########################################### [100%]
    1:Atlas ########################################### [100%]

Atlas配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 1.编辑配置文件
cat /usr/local/mysql-proxy/conf/test.cnf

[mysql-proxy]
#带#号的为非必需的配置项目
#管理接口的用户名
admin-username = user

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

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

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

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

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

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

#工作线程数,对Atlas的性能有很大影响,可根据情况适当设置,根据CPU核心数来设置(查看cpu核心方式:lscpu/top 1)
event-threads = 8

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

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

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

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

#实例名称,用于同一台机器上多个Atlas实例间的区分(和配置文件名一致)
instance = test

#Atlas监听的工作接口IP和端口(避免和数据库端口冲突)
proxy-address = 0.0.0.0:3307

#Atlas监听的管理接口IP和端口(0-65535)
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


# 2.启动atlas
/usr/local/mysql-proxy/bin/mysql-proxyd base start
cd /usr/local/mysql-proxy/bin && ./mysql-proxyd test start

Atlas多实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1.配置文件修改实例名称
# 实例名称,用于同一台机器上多个Atlas实例间的区分
instance = base

# 2.配置文件名与实例名称一致
ll /usr/local/mysql-proxy/conf/base.cnf

# 3.端口不能冲突
#Atlas监听的工作接口IP和端口(避免和数据库端口冲突)
proxy-address = 0.0.0.0:3308
#Atlas监听的管理接口IP和端口(0-65535)
admin-address = 0.0.0.0:5678

# 4.启动
/usr/local/mysql-proxy/bin/mysql-proxyd base start

Atlas管理接口

Atlas管理接口语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# mysql -uuser -ppwd -h127.0.0.1 -P2345

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 |
+---------------------------+-----------------------------------------------------+

语法结构

  • Atlas管理接口语法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    SELECT * FROM help            # 获取Atlas管理语法帮助
    SELECT * FROM backends # 查看后端代理的所有数据库以及状态
    SET OFFLINE $backend_id # 下线指定DB
    SET ONLINE $backend_id # 上线指定DB
    ADD MASTER $backend # 添加一台主库
    ADD SLAVE $backend # 添加一台从库
    REMOVE BACKEND $backend_id # 删除一个代理的后端DB
    SELECT * FROM clients # 查看过滤允许的客户端
    ADD CLIENT $client # 添加一个客户端(允许连接atlas的客户端)
    REMOVE CLIENT $client # 删除一个客户端(不允许连接atlas的客户端)
    SELECT * FROM pwds # 查看atlas支持的MySQL用户和密码
    ADD PWD $pwd # 使用接口添加用户(输入密码自动加密)
    ADD ENPWD $pwd # 使用接口添加用户(手动输入加密密码)
    REMOVE PWD $pwd # 使用接口删除用户和密码
    SAVE CONFIG # 将所有操作保存到配置文件
    SELECT VERSION # 查看Atlas版本
  • 管理接口语法示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    # 查看后端代理的所有数据库以及状态
    mysql> SELECT * FROM backends;
    +-------------+------------------+-------+------+
    | backend_ndx | address | state | type |
    +-------------+------------------+-------+------+
    | 1 | 172.16.1.55:3306 | down | rw |
    | 2 | 172.16.1.52:3306 | up | ro |
    | 3 | 172.16.1.53:3306 | up | ro |
    | 4 | 172.16.1.54:3306 | up | ro |
    +-------------+------------------+-------+------+

    # 下线指定DB
    mysql> set offline 2;
    +-------------+------------------+---------+------+
    | backend_ndx | address | state | type |
    +-------------+------------------+---------+------+
    | 2 | 172.16.1.52:3306 | offline | ro |
    +-------------+------------------+---------+------+

    # 上线指定DB
    mysql> set online 2;
    +-------------+------------------+---------+------+
    | backend_ndx | address | state | type |
    +-------------+------------------+---------+------+
    | 2 | 172.16.1.52:3306 | unknown | ro |
    +-------------+------------------+---------+------+

    # 添加一台主库
    mysql> add master 172.16.1.88:3306;
    mysql> SELECT * FROM backends;
    +-------------+------------------+-------+------+
    | backend_ndx | address | state | type |
    +-------------+------------------+-------+------+
    | 1 | 172.16.1.55:3306 | down | rw |
    | 2 | 172.16.1.88:3306 | down | rw |
    | 3 | 172.16.1.53:3306 | up | ro |
    | 4 | 172.16.1.54:3306 | up | ro |
    | 5 | 172.16.1.52:3306 | up | ro |
    +-------------+------------------+-------+------+

    # 添加一台从库
    mysql> add slave 172.16.1.89:3306;
    mysql> SELECT * FROM backends;
    +-------------+------------------+---------+------+
    | backend_ndx | address | state | type |
    +-------------+------------------+---------+------+
    | 1 | 172.16.1.55:3306 | down | rw |
    | 2 | 172.16.1.88:3306 | down | rw |
    | 3 | 172.16.1.53:3306 | up | ro |
    | 4 | 172.16.1.54:3306 | up | ro |
    | 5 | 172.16.1.52:3306 | up | ro |
    | 6 | 172.16.1.89:3306 | unknown | ro |
    +-------------+------------------+---------+------+

    # 删除一个后端代理节点
    mysql> remove backend 2;

    # 查看过滤允许的客户端
    SELECT * FROM clients
    mysql> select * from clients;
    +----------+
    | client |
    +----------+
    | 10.0.0.7 |
    +----------+

    # 添加一个客户端(允许连接atlas的客户端)
    mysql> add client 10.0.0.7;
    mysql> save config;

    # 删除一个客户端(不允许连接atlas的客户端)
    mysql> remove client 10.0.0.7;
    mysql> SELECT * FROM clients;

    # 查看atlas支持的MySQL用户和密码
    mysql> select * from pwds;
    +----------+--------------------------+
    | username | password |
    +----------+--------------------------+
    | root | igdHsEAe7Uca8s/oWZlMvQ== |
    | mha | O2jBXONX098= |
    +----------+--------------------------+

    # 使用接口添加用户
    mysql> add pwd hcl:123;
    mysql> select * from pwds;
    +----------+--------------------------+
    | username | password |
    +----------+--------------------------+
    | root | igdHsEAe7Uca8s/oWZlMvQ== |
    | mha | O2jBXONX098= |
    | hcl | 3yb5jEku5h4= |
    +----------+--------------------------+

    # 使用接口添加一个加过密的密码用户
    mysql> add enpwd hcl2:O2jBXONX098=;
    mysql> select * from pwds;
    +----------+--------------------------+
    | username | password |
    +----------+--------------------------+
    | root | igdHsEAe7Uca8s/oWZlMvQ== |
    | mha | O2jBXONX098= |
    | hcl | 3yb5jEku5h4= |
    | hcl2 | O2jBXONX098= |
    +----------+--------------------------+

    # 删除用户和密码
    mysql> remove pwd hcl2;
    mysql> select * from pwds;
    +----------+--------------------------+
    | username | password |
    +----------+--------------------------+
    | root | igdHsEAe7Uca8s/oWZlMvQ== |
    | mha | O2jBXONX098= |
    | hcl | 3yb5jEku5h4= |
    +----------+--------------------------+

    # 将所有操作保存到配置文件
    mysql> save config;

    # 查看Atlas版本
    mysql> SELECT VERSION;
    +---------+
    | version |
    +---------+
    | 2.2.1 |
    +---------+

MHA结合Atlas使用

  • 编写Atlas自动转移读写分离脚本

    • 脚本执行流程

      1
      2
      3
      4
      # Atlas结合MHA一起使用(MHA切换时)
      mysql> remove backend 4; # 摘除被提升为主库的从库
      mysql> add slave 172.16.1.52:3306; # 将旧主库加入到从库中
      mysql> save config; # 保存atlas配置
    • 编写脚本

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      vim atlas_auto.sh
      #!/bin/bash
      atlas_user='user'
      atlas_pass='pwd'
      atlas_port='2345'
      atlas_ip='172.16.1.51'
      atlas_manager="mysql -u${atlas_user} -p${atlas_pass} -h${atlas_ip} -P${atlas_port}"
      mha_log_path='/etc/mha/app1/log/manager.log'
      old_master_ip=`sed -nr 's#(.*)\(.*\) \(current master\)$#\1#gp' ${mha_log_path}|head -1`
      new_master_ip=`sed -nr 's#(.*)\(.*\) \(new master\)$#\1#gp' ${mha_log_path}`
      new_master_id=`$atlas_manager -e 'select * from backends'|grep ${new_master_ip}|awk '{print $1}'`

      # 摘除被提升为主库的从库
      ${atlas_manager} -e "remove backend ${new_master_id}"
      # 将旧主库加入到从库中
      ${atlas_manager} -e "add slave ${old_master_ip}:3306"
      # 保存atlas配置
      ${atlas_manager} -e "save config"
  • 在MHA执行脚本中调用自动转移读写分离脚本

    1
    2
    3
    4
    5
    6
    # 编辑mha执行脚本文件
    vim /etc/mha/app1/script/master_ip_failover
    sub start_vip() {
    `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
    `/bin/sh -x /etc/mha/app1/script/atlas_auto.sh`
    }
  • 测试执行结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    # 1.启动MHA
    [root@db03 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /etc/mha/app1/log/manager.log 2>&1 &

    # 2.检查mha状态
    [root@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
    app1 (pid:20045) is running(0:PING_OK), master:172.16.1.51

    # 3.查询后端代理的所有数据库以及状态
    mysql -uuser -ppwd -h172.16.1.51 -P2345 -e 'select * from backends'
    +-------------+------------------+-------+------+
    | backend_ndx | address | state | type |
    +-------------+------------------+-------+------+
    | 1 | 172.16.1.55:3306 | down | rw |
    | 2 | 172.16.1.53:3306 | up | ro |
    | 3 | 172.16.1.54:3306 | up | ro |
    | 4 | 172.16.1.52:3306 | up | ro |
    +-------------+------------------+-------+------+

    # 停止主库
    /etc/init.d/mysqld stop
    Shutting down MySQL............ SUCCESS!

    # 查询后端代理的所有数据库以及状态
    mysql -uuser -ppwd -h172.16.1.51 -P2345 -e 'select * from backends'
    +-------------+------------------+-------+------+
    | backend_ndx | address | state | type |
    +-------------+------------------+-------+------+
    | 1 | 172.16.1.55:3306 | down | rw |
    | 2 | 172.16.1.53:3306 | up | ro |
    | 3 | 172.16.1.54:3306 | up | ro |
    | 4 | 172.16.1.51:3306 | up | ro |
    +-------------+------------------+-------+------+

    # 执行从库自动恢复脚本
    sh /etc/mha/app1/script/mha.sh