之前也介绍 MySQL 高可用相关的文章:
MySQL 同步复制及高可用方案总结
MySQL route 介绍
什么是 MySQL route
MySQL Router 是处于应用 client 和 dbserver 之间的轻量级代理程序, 它能检测, 分析和转发查询到后端数据库实例, 并把结果返回给 client. 是 MySQL-proxy 的一个替代品. 其架构图和功能如下.
(1)Router 实现读写分离, 程序不是直接连接数据库 IP, 而是固定连接到 MySQL router.MySQL Router 对前端应用是透明的. 应用程序把 MySQL Router 当作是普通的 MySQL 实例, 把查询发给 MySQL Router, 而 MySQL Router 会把查询结果返回给前端的应用程序.
(2) 从数据库服务器故障, 业务可以正常运行. 由 MySQL Router 来进行自动下线不可用服务器. 程序配置不需要任何修改.
(3) 主数据库故障, 由 MySQL Router 来决定主从自动切换, 业务可以正常访问. 程序配置不需要做任何修改.
读写分离原理
MySQL Router 接受前端应用程序请求后, 根据不同的端口来区分读写, 把连接读写端口的所有查询发往主库, 把连接只读端口的 select 查询以轮询方式发往多个从库, 从而实现读写分离的目的. 读写返回的结果会交给 MySQL Router, 由 MySQL Router 返回给客户端的应用程序.
MySQL router 用途
MySQL Router 的主要用途是读写分离, 主主故障自动切换, 负载均衡, 连接池等.
MySQL router 主主故障自动切换的坑
MySQL router 主主故障切换功能经过测试没有问题, 但是有一个比较大的坑需要注意, 具体是什么坑和解决方法在文章末尾, 因为你之前要是没用接触过 MySQL router 估计以我的表达能力, 说了你就晕了.
MySQL router 实验架构介绍
实验环境架构图如下:
安装部署 MySQL route
(1) 下载地址: 提供不同平台, 二进制包和 rpm 包, 选择合适安装方式即可, 我这里使用二进制包安装
(2) 解压安装
- [root@c7-node1 ~]# tar xf MySQL-router-2.0.3-Linux-glibc2.12-x86-64bit.tar.gz -C /usr/local/
- [root@c7-node1 ~]# cd /usr/local/
- [root@c7-node1 local]# ln -s MySQL-router-2.0.3-Linux-glibc2.12-x86-64bit/ MySQL-router
- [root@c7-node1 local]# cd MySQL-router
- [root@c7-node1 MySQL-router]# ll
- total 0
- drwxr-xr-x 2 7161 wheel 24 Feb 23 2016 bin
- drwxr-xr-x 4 7161 wheel 36 Feb 23 2016 include
- drwxr-xr-x 3 7161 wheel 150 Feb 23 2016 lib
- drwxrwxr-x 2 7161 wheel 6 Feb 23 2016 run
- drwxr-xr-x 3 7161 wheel 16 Feb 23 2016 share
(3) 配置
1, 创建配置文件目录, 复制模版配置文件
- [root@c7-node1 MySQL-router]# mkdir /etc/MySQL-route/
- [root@c7-node1 MySQL-router]# cp share/doc/mysqlrouter/sample_mysqlrouter.INI /etc/MySQL-route/mysqlrouter.conf
2, 配置文件设置, 日志目录需要自己手动创建
- [root@node1 ~]# cat /etc/MySQL-route/mysqlrouter.conf
- [DEFAULT]
- # 日志存放目录
- logging_folder = /data/log/MySQL-route
- # 插件存放目录
- plugin_folder = /usr/local/MySQL-router/lib/mysqlrouter
- # 配置文件存放目录
- config_folder = /etc/MySQL-route
- # 运行目录
- runtime_folder = /var/run
- [logger]
- # 日志运行级别
- level = INFO
- # 主节点故障转移配置
- [routing:basic_failover]
- # 写节点地址
- bind_address=192.168.100.10
- # 写节点端口
- bind_port = 7001
- # 模式, 读写
- mode = read-write
- # 主节点地址: 默认情况下第一台主数据库为写主库, 当第一台主数据库 DOWN 机后, 第二台数据库被提升为主库
- destinations = 192.168.100.11:3306,192.168.100.12:3306
- # 从节点负载均衡配置
- [routing:balancing]
- # 绑定的 IP 地址
- bind_address=192.168.100.10
- # 监听的端口
- bind_port = 7002
- # 连接超时时间
- connect_timeout = 3
- # 最大连接数
- max_connections = 1024
- # 后端服务器地址
- destinations = 192.168.100.12:3306,192.168.100.13:3306
- # 模式: 读还是写
- mode = read-only
- [keepalive]
- interval = 60
日志目录创建及授权
- [root@c7-node1 ~]# mkdir /data/log/MySQL-route/
- [root@c7-node1 ~]# chown MySQL:MySQL /data/log/MySQL-route/
(4) 启动: MySQL route 官方没有提供启动脚本, 需要自己编写
- [root@c7-node1 ~]# cat /usr/lib/systemd/system/mysqlrouter.service
- [Unit]
- Description=MySQL Router
- After=syslog.target
- After=network.target
- [Service]
- Type=simple
- User=MySQL
- Group=MySQL
- ExecStart=/usr/local/MySQL-router/bin/mysqlrouter -c /etc/MySQL-route/mysqlrouter.conf
- PrivateTmp=true
- [Install]
- WantedBy=multi-user.target
5, 启动服务
- [root@c7-node1 ~]# systemctl enable mysqlrouter
- [root@c7-node1 ~]# systemctl start mysqlrouter
读写分离测试
1, 创建测试帐号, 测试库
- MariaDB [(none)]> create database mysql_route;
- MariaDB [(none)]> GRANT all ON mysql_route.* TO 'route'@'%' IDENTIFIED BY 'route';
- MariaDB [(none)]> FLUSH PRIVILEGES;
2, 验证读负载均衡: 从结果看到每次读都是访问不同的主机
3, 验证写: 可以看到每次写都是写到主节点
从库 down 机测试
下面是从库 down 机测试截图, 可以看到两个节点都正常的情况下, 是轮训从两个从库取数据, 如果其中一个从库故障, 那么 MySQL router 会自动下线故障的从库, 如果从库恢复, MySQL router 会自动把从库上线.
主主故障切换测试
验证: 正常情况下数据写入都是写到主库
我们手动停止主库的 MySQL 服务, 模拟故障, 再次写入, 可以看到写入数据的节点是主库的备份节点.
注意:
1, 备份从库不能打开 read-only = on, 不然切换之后写入会报错
2, 第一台主库 DOWN 后, MySQL Router 如何处理?
默认情况下第一台主数据库为写主库, 当第一台主数据库 DOWN 机后, 第二台数据库被提升为主库, 稍后如果第一台主库被修复后, 那么默认仍然连接第二台为主库进行读写, 不会自动切回到第一台主库.
3, 如果第一台主数据库被修复后, 又希望切换回第一台主库, 怎么办?
可以重启 MySQL Router
主主故障切换的坑
MySQL router 的主主故障切换如果是运行在一主一从的情况下, 从库作为主库的备份, 这种情况是使用 MySQL router 主主故障切换是没有问题的, 但是在一主多从的情况下使用主主故障切换就会处在如下问题.
在一主多从的情况, 如果主库 down 机, 切换到备份节点, 其他从库的主库地址连接还是故障的主库, 这样就会造成一个从库 slave_io 线程 connecting 状态, 造成复制延迟. 我之前的主库地址是 192.168.10.11, 备份主库地址是 192.168.10.12, 但是主库故障之后, MySQL route 可以把写请求路由到新的主库, 但是从库尝试连接的主库还是 192.168.10.11, 这种情况是正常的, 因为 MySQL router 主主故障切换原理就是这样, 但是生产环境就不能这么玩了.
解决办法:
1, 在切换时需要自己编写脚本触发一个 shell 脚本或者 event 来处理重连的问题.
2, 不使用 MySQL router 主主故障转移功能, 而是自己使用其他方式保证 MySQL 主库高可用.
版权申明: 作者: 西门飞冰, 一名 90 后 it 男, 一直在北京工作, 热爱运动, 热爱冒险, 热爱旅行. 由作者原创投稿, 版权归原创者所有. 除非无法确认, 我们都会标明作者及出处, 如有侵权烦请告知, 我们会立即删除并表示歉意, 谢谢.
关注民工哥技术之路 微信公众号对话框回复关键字: 1024 可以获取一份最新整理的技术干货: 包括系统运维, 数据库, Redis,MogoDB, 电子书, Java 基础课程, Java 实战项目, 架构师综合教程, 架构师实战项目, 大数据, Docker 容器, ELK Stack, 机器学习, BAT 面试精讲视频等.
来源: https://segmentfault.com/a/1190000020751216