ITPub博客

首页 > 数据库 > MySQL > MySQL中间件--MySQL Router(mysqlrouter)

MySQL中间件--MySQL Router(mysqlrouter)

原创 MySQL 作者:lhrbest 时间:2020-02-27 17:16:04 0 删除 编辑

MySQL中间件--MySQL Router(mysqlrouter)


https://wxy0327.blog.csdn.net/article/details/100518636

https://blog.csdn.net/wzy0623/article/details/81103469



各种安装包的下载地址为:

https://dev.mysql.com/downloads/router/

其它情况的安装可参考:

https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation.html


 

1.1   二进制安装

MySQL Router 的安装过程依赖于所使用的操作系统和安装介质,二进制包的安装通常非常简单,而源码包则需要先编译再安装。例如在 Linux 上的安装最新的 MySQL Router 二进制包,只需要用 mysql 用户执行一条解压命令就完成了:

tar -Jxvf mysql-router-8.0.17-linux-glibc2.12-x86_64.tar.xz

mv ./mysql-router-8.0.19-linux-glibc2.12-x86_64  /usr/local

解压后生成如下目录:

[root@rhel6lhr mysql-router-8.0.19-linux-glibc2.12-x86_64]$ ll

total 124

-rw-r--r-- 1 7161 31415 102977 Dec 10 03:53 LICENSE.router

-rw-r--r-- 1 7161 31415    700 Dec 10 03:53 README.router

drwxr-xr-x 2 root root    4096 Feb 27 15:59 bin

drwxr-xr-x 4 root root    4096 Feb 27 15:59 lib

drwxr-xr-x 3 root root    4096 Feb 27 15:59 man

drwxr-xr-x 3 root root    4096 Feb 27 15:59 share

bin 目录下存放的是可执行文件,可将该目录添加到 PATH 环境变量中方便执行,例如:

export PATH=$PATH:/usr/local/mysql-router-8.0.19-linux-glibc2.12-x86_64/bin

echo 'export PATH=$PATH:/usr/local/mysql-router-8.0.19-linux-glibc2.12-x86_64/bin' >> /etc/profile

source /etc/profile

然后就可以执行mysqlrouter 命令,如检查版本或显示帮助:

mysqlrouter --version

mysqlrouter --help

 

1   启动

数据库架构为1 2 从:

mysqld_multi report 57193324-57193326

 

 

MySQL Router 启动时需要读取其配置文件,获取基本连接路由信息。 Router 插件执行基于连接的路由,这意味着它将数据包转发到服务器而不检查它们。这是一种提供高吞吐量的简单方法。一个基本的连接路由设置如下所示:

[logger]

level = INFO

 

[routing:secondary]

bind_address = 192.168.59.130

bind_port = 7001

destinations = 192.168.59.131:3324,192.168.59.132:3325,192.168.59.133:3326

routing_strategy = round-robin

 

[routing:primary]

bind_address = 192.168.59.130

bind_port = 7002

destinations = 192.168.59.131:3324,192.168.59.132:3325,192.168.59.133:3326

routing_strategy = first-available

这里设置了两个路由策略:通过本地7001 端口,循环连接到 192.168.59.131:3324 192.168.59.132:3325 192.168.59.133:3326 三个 MySQL 实例,由 round-robin 路由策略所定义;通过本地 7002 端口,对同样的三个 MySQL 实例设置首个可用策略。首个可用策略使用目标列表中的第一个可用服务器,即当 192.168.59.131:3324 可用时,所有 7002 端口的连接都转发到它,否则转发到 192.168.59.132:3325 ,以此类推。 Router 不会检查数据包,也不会根据分配的策略或模式限制连接,因此应用程序可以据此确定将读写请求发送到不同的服务器。

本例中可将读请求发送到本地7001 端口,将读负载均衡到三台服务器。同时将写请求发送到 7002 ,这样只写一个服务器,从而实现的读写分离。

启动mysqlrouter ,启动之前需要确保 7001 7002 端口没有被占用:

mysqlrouter -c /etc/mysqlrouter.conf &

查看进程确认MySQL Router 已经启动:

[root@rhel6lhr ~]$ ps -ef | grep router

root      9833  9818  0 16:25 pts/2    00:00:00 tailf /usr/local/mysql-router-8.0.19-linux-glibc2.12-x86_64/mysqlrouter.log

root     10096  2229  0 16:27 pts/0    00:00:00 mysqlrouter -c /etc/mysqlrouter.conf

root     10154  2229  0 16:28 pts/0    00:00:00 grep router

 

缺省的日志文件中显示如下信息:

/usr/local/mysql-router-8.0.19-linux-glibc2.12-x86_64/mysqlrouter.log

 

2020-02-27 16:27:27 routing INFO [7f9c4bfbb700] [routing:primary] started: listening on 192.168.59.130:7002, routing strategy = first-available

2020-02-27 16:27:27 routing INFO [7f9c4b5ba700] [routing:secondary] started: listening on 192.168.59.130:7001, routing strategy = round-robin

 

端口监听情况:

[root@rhel6lhr mysql-router-8.0.19-linux-glibc2.12-x86_64]$ netstat -tnlp | grep 700

tcp        0      0 ::1:7001                    :::*                        LISTEN      10096/mysqlrouter   

tcp        0      0 ::1:7002                    :::*                        LISTEN      10096/mysqlrouter

 

 

2   停止

可以在网络上的单台或多台主机上运行多个MySQL 路由器实例,而无需将 MySQL Router 隔离到单个机器上。这是因为 MySQL Router 对任何特定服务器或主机都不具有亲和性。要停止 MySQL Router ,只需用 kill killall 命令直接杀掉相关进程。 MySQL Router 只起到一个转发流量的作用,它实在太“轻”了,以至都没有一个单独的停止命令。


 

1   高可用测试

 

由上可见,发送到本地7001 端口的请求,被循环转发到三个服务器,而发送到本地 7002 端口的请求,全部被转发到 192.168.59.130:3324

 

1.1   测试负载均衡

for i in $(seq 1 10); do mysql -uroot -plhr -h192.168.59.130 -P7001 -e 'select @@server_id;'; done | egrep '[0-9]'

 

[root@rhel6lhr ~]$ for i in $(seq 1 10); do mysql -uroot -plhr -h192.168.59.130 -P7001 -e 'select @@server_id;'; done | egrep '[0-9]'         

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193325

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193325

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193325

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193325

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193325

 

1.2   测试读写分离

for i in $(seq 1 10); do mysql -uroot -plhr -h192.168.59.130 -P7002 -e 'select @@server_id;'; done | egrep '[0-9]'

 

[root@rhel6lhr ~]$ for i in $(seq 1 10); do mysql -uroot -plhr -h192.168.59.130 -P7002 -e 'select @@server_id;'; done | egrep '[0-9]'

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193324

Warning: Using a password on the command line interface can be insecure.

57193324

 

 

1   虚拟机中的配置

 

1、 数据库在虚拟机中

2、 mysqlrouter windows 的主机中

 

配置文件:

[logger]

level = INFO

 

[routing:secondary]

bind_address = 192.168.59.1

bind_port = 7001

destinations = 192.168.59.131:3324,192.168.59.132:3325,192.168.59.133:3326

routing_strategy = round-robin

 

[routing:primary]

bind_address = 192.168.59.1

bind_port = 7002

destinations = 192.168.59.131:3324,192.168.59.132:3325,192.168.59.133:3326

routing_strategy = first-available

启动:

mysqlrouter -c "D:\Program Files\MySQL\mysql-router-8.0.19-winx64\mysqlrouter.ini"

 

连接:

mysql -uroot -plhr -h192.168.59.1 -P7001

 


 





MySQL Router 8 详解



 MySQL Router最早是作为MySQL-Proxy的替代方案出现的。作为一个轻量级中间件,MySQL Router可在应用程序和后端MySQL服务器之间提供透明路由和负载均衡,从而有效提高MySQL数据库服务的高可用性与可伸缩行。


        MySQL Router 2.0是其初始版本,适用于MySQL Fabric用户,但已被弃用,不再支持。MySQL Router 2.1为支持MySQL InnoDB Cluster而引入,MySQL Router 8.0则是MySQL Router 2.1上的扩展,版本号与MySQL服务器版本号保持一致。即Router 2.1.5作为Router 8.0.3(以及MySQL Server 8.0.3)发布,2.1.x分支被8.0.x取代。这两个分支完全兼容。当前最新版本为8.0.17,MySQL强烈建议使用Router 8与MySQL Server 8和5.7一起使用。


一、功能介绍

1. 透明路由

        MySQL Router通过智能地将客户端连接路由到MySQL服务器来简化应用程序开发。MySQL使用组复制在多个服务器之间复制数据,当服务器发生故障时执行自动故障转移,基于paxos协议在剩余实例中选举一个新的主库。这里存在一个问题,如果应用程序直连主库,当发生主库切换时可用的数据库IP地址发生变化,客户端应用程序必须自行修改它的连接配置。这种方案极不现实,因为需要应用程序了解组复制的拓扑结构并知道哪个MySQL实例是主库,对于应用程序显然是强人所难,这些处理逻辑本应对应用透明。


        而这正是MySQL Router的用武之地。当与InnoDB Cluster一起使用时,MySQL Router充当代理,向应用程序隐藏网络上的多个MySQL实例,并将数据请求映射到其中一个集群实例。只要有足够的在线副本并且组件之间的通信完好无损,客户端就能够连接其中一个实例,保持对外服务的连续性。应用程序要做的只是连接到Router,而不是直连MySQL数据库实例,其它的交给Router处理即可。


        MySQL Router的推荐部署模型是与InnoDB Cluster集成,其中Router与应用程序最好位于同一主机上。


2. 元数据缓存

        MySQL Router处于应用程序和MySQL服务器之间。当应用程序连接到Router时,Router从其候选池中选择合适的MySQL服务器连接,此后Router转发应用程序和MySQL之间的所有往返网络流量。


        MySQL Router保留在线MySQL服务器的缓存列表,或配置的InnoDB Cluster的拓扑和状态。Router启动时,列表从Router的配置文件加载。当使用--bootstrap选项引导Router时,此列表由InnoDB群集服务器生成。为了更新缓存,Router元数据缓存组件与包含元数据的InnoDB Cluster服务器之一保持连接,通过从该MySQL实例的performance_schema库表查询元数据和实时状态信息来实现。每当修改InnoDB集群时都会更改集群元数据,并且只要检测到集群状态更改,就会通过MySQL服务器的Group Replication插件实时更新performance_schema库表。


        当Router检测到连接的MySQL服务器关闭时,它会尝试连接到不同的MySQL服务器以从新的服务器获取元数据和InnoDB Cluster状态。关闭的MySQL服务器的应用程序连接会自动关闭。应用程序必须重新连接到Router,这要求应用程序实现重连机制。Router将它们重定向到在线MySQL服务器。


3. 简单重定向

        Router将MySQL连接重定向到可用的MySQL服务器,这意味着数据包是在未经检查的情况下整体路由的。如果连接失败,应用程序须要重试连接,MySQL Router在尝试连接失败后选择新的MySQL服务器。这被称为简单重定向连接路由,因为它需要应用程序重试连接。也就是说,如果从MySQL Router到MySQL服务器的连接中断,则应用程序会遇到连接失败,但新的连接尝试会触发Router查找并连接到另一台MySQL服务器。路由连接的服务器和路由策略在配置文件中定义。


        使用MySQL Router不需要特定的库或接口,与不使用Router相比,应用程序所感知的唯一区别是如何建立与MySQL服务器的连接。因为MySQL Router在尝试连接时只是单纯重定向,并不读取数据包或执行分析,所以应用程序需要捕获连接错误并重试连接到Router。


        使用MySQL Router的工作流程如下:


MySQL客户端连接到MySQL Router。

Router检查可用的MySQL服务器。

Router打开一个适用MySQL服务器的连接。

Router在应用程序和MySQL服务器之间来回转发数据包

如果连接的MySQL服务器出现故障, Router将断开连接。当应用程序重试连接到Router时,Router选择另一个可用MySQL服务器。

        部署MySQL Router时建议但不强制遵循两点:


在与应用程序相同的主机上安装并运行MySQL Router。

使用配置文件中的bind_port = 127.0.0.1:<port>将 Router绑定到localhost,或者禁用TCP连接(--conf-skip-tcp)并将其限制为仅使用Unix套接字连接(--conf-use-sockets)。

        建议主要出于性能考虑。每当在网络中引入通信组件时,都会产生一定的开销,并且会受到工作负载的严重影响。幸运的是,MySQL Router的性能影响非常小。官方文档显示,当前版本的简单重定向连接路由,其速度与直连数据库相比仅慢约1%。


4. MySQL Router 8.0的新特性

        较之以前2.x版本,MySQL Router 8.0新增了如下主要功能:


添加了可选的routing_strategy配置选项。可用值为first-available、next-available、round-robin和round-robin-with-fallback。以前版本中,这些策略对应mode选项中的调度模式,其中read-write对应first-available,而read-only对应round-robin。它们保留了这些模式的先前行为。

添加了--ssl-key和--ssl-cert命令行选项,指定客户端证书和私钥以方便客户端身份验证。用于使用REQUIRE X509创建root帐户时。

添加了connect_timeout和read_timeout元数据配置文件选项。它们在[DEFAULT]命名空间下定义,并影响元数据服务器连接等内部操作。

Bootstrap接受InnoDB Cluster的任何成员,并自动查找并重新连接到可写服务器。以前只接受主库。

Bootstrap接受--config选项并读取[logger]级别选项的定义。

最大并发客户端连接数从500增加到5000。

添加了一个新的mysqlrouter_plugin_info实用程序来帮助调试MySQL Router插件。


二、安装与启动

1. 安装

        MySQL Router的安装过程依赖于所使用的操作系统和安装介质,二进制包的安装通常非常简单,而源码包则需要先编译再安装。例如在Linux上的安装最新的MySQL Router二进制包,只需要用mysql用户执行一条解压命令就完成了:


tar -Jxvf mysql-router-8.0.17-linux-glibc2.12-x86_64.tar.xz

        解压后生成如下目录:


[mysql@hdp1~]$ll mysql-router-8.0.17-linux-glibc2.12-x86_64

total 108

drwxrwxr-x 2 mysql mysql    126 Sep  2 15:26 bin

drwxrwxr-x 3 mysql mysql   4096 Sep  2 15:26 lib

-rw-r--r-- 1 mysql mysql 101805 Jun 25 18:23 LICENSE.router

drwxrwxr-x 3 mysql mysql     17 Sep  2 15:22 man

-rw-r--r-- 1 mysql mysql    700 Jun 25 18:23 README.router

drwxrwxr-x 3 mysql mysql     16 Sep  2 15:22 share

bin目录下存放的是可执行文件,可将该目录添加到PATH环境变量中方便执行,例如:


export PATH=.:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/home/mysql/mysql-5.6.14/bin:/home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin;

然后就可以执行mysqlrouter命令,如检查版本或显示帮助:


[mysql@hdp1~]$mysqlrouter --version

MySQL Router  Ver 8.0.17 for linux-glibc2.12 on x86_64 (MySQL Community - GPL)

[mysql@hdp1~]$mysqlrouter --help

[mysql@hdp1~]$mysqlrouter --help

MySQL Router  Ver 8.0.17 for linux-glibc2.12 on x86_64 (MySQL Community - GPL)

Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.

 

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

 

Configuration read from the following files in the given order (enclosed

in parentheses means not available for reading):

  (/home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/.././mysqlrouter.conf)

  (/home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/.././mysqlrouter.ini)

  (/home/mysql/.mysqlrouter.conf)

  (/home/mysql/.mysqlrouter.ini)

 

...

        各种安装包的下载地址为https://dev.mysql.com/downloads/router/。其它情况的安装可参考https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation.html。


2. 启动

        MySQL Router启动时需要读取其配置文件,获取基本连接路由信息。Router插件执行基于连接的路由,这意味着它将数据包转发到服务器而不检查它们。这是一种提供高吞吐量的简单方法。一个基本的连接路由设置如下所示:


[logger]

level = INFO

 

[routing:secondary]

bind_address = localhost

bind_port = 7001

destinations = 172.16.1.125:3306,172.16.1.126:3306,172.16.1.127:3306

routing_strategy = round-robin

 

[routing:primary]

bind_address = localhost

bind_port = 7002

destinations = 172.16.1.125:3306,172.16.1.126:3306,172.16.1.127:3306

routing_strategy = first-available

        这里设置了两个路由策略:通过本地7001端口,循环连接到172.16.1.125:3306、172.16.1.126:3306、172.16.1.127:3306三个MySQL实例,由round-robin路由策略所定义;通过本地7002端口,对同样的三个MySQL实例设置首个可用策略。首个可用策略使用目标列表中的第一个可用服务器,即当172.16.1.125:3306可用时,所有7002端口的连接都转发到它,否则转发到172.16.1.126:3306,以此类推。Router不会检查数据包,也不会根据分配的策略或模式限制连接,因此应用程序可以据此确定将读写请求发送到不同的服务器。本例中可将读请求发送到本地7001端口,将读负载均衡到三台服务器。同时将写请求发送到7002,这样只写一个服务器,从而实现的读写分离。


        将以上配置保存到/home/mysql/.mysqlrouter.conf文件,并后台启动MySQL Router:


[mysql@hdp1~]$mysqlrouter -c /home/mysql/.mysqlrouter.conf &

查看进程确认MySQL Router已经启动:


[mysql@hdp1~]$ps -ef | grep router

mysql    327410 326543  0 16:31 pts/0    00:00:00 mysqlrouter -c /home/mysql/.mysqlrouter.conf

...

缺省的日志文件中显示如下信息:


[mysql@hdp1~]$more ~/mysql-router-8.0.17-linux-glibc2.12-x86_64/mysqlrouter.log 

2019-09-02 16:42:36 routing INFO [7f151540b700] [routing:primary] started: listening on localhost:7002, routing strategy = first-available

2019-09-02 16:42:36 routing INFO [7f1514c0a700] [routing:secondary] started: listening on localhost:7001, routing strategy = round-robin

[mysql@hdp1~]$

查看监听状态:


[mysql@hdp1~]$netstat -tnlp

(Not all processes could be identified, non-owned process info

 will not be shown, you would have to be root to see it all.)

Active Internet connections (only servers)

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    

tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   

tcp        0      0 127.0.0.1:199           0.0.0.0:*               LISTEN      -                   

tcp6       0      0 :::80                   :::*                    LISTEN      -                   

tcp6       0      0 :::22                   :::*                    LISTEN      -                   

tcp6       0      0 ::1:7001                :::*                    LISTEN      329852/mysqlrouter  

tcp6       0      0 ::1:7002                :::*                    LISTEN      329852/mysqlrouter  

[mysql@hdp1~]$

        现在,MySQL Router正在侦听端口7001和7002,并将请求发送到适当的MySQL实例:


[mysql@hdp1~]$mysql -uwxy -p123456 -P7001 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

+------------+

| @@hostname |

+------------+

| hdp2       |

+------------+

[mysql@hdp1~]$mysql -uwxy -p123456 -P7001 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

+------------+

| @@hostname |

+------------+

| hdp3       |

+------------+

[mysql@hdp1~]$mysql -uwxy -p123456 -P7001 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

+------------+

| @@hostname |

+------------+

| hdp4       |

+------------+

[mysql@hdp1~]$mysql -uwxy -p123456 -P7001 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

+------------+

| @@hostname |

+------------+

| hdp2       |

+------------+

[mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

+------------+

| @@hostname |

+------------+

| hdp2       |

+------------+

[mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

+------------+

| @@hostname |

+------------+

| hdp2       |

+------------+

[mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

+------------+

| @@hostname |

+------------+

| hdp2       |

+------------+

[mysql@hdp1~]$

        由上可见,发送到本地7001端口的请求,被循环转发到三个服务器,而发送到本地7002端口的请求,全部被转发到172.16.1.125:3306。


        routing_strategy是MySQL Router的核心选项,从8.0.4版本开始引入,当前有效值为first-available、next-available、round-robin、round-robin-with-fallback。顾名思义,该选项实际控制路由策略,即客户端请求最终连接到哪个MySQL服务器实例。相对于以前版本mode的选项,routing_strategy选项更为灵活,并且不能同时设置routing_strategy和mode,静态路由的设置只能选择其中之一。对于InnoDB Cluster而言,该设置时可选的,缺省使用round-robin策略。


round-robin:每个新连接都以循环方式连接到下一个可用的服务器,以实现负载平衡。

round-robin-with-fallback:用于InnoDB Cluster。每个新的连接都以循环方式连接到下一个可用的SECONDARY服务器。如果SECONDARY服务器不可用,则以循环方式使用PRIMARY服务器。

first-available:新连接从目标列表路由到第一个可用服务器。如果失败,则使用下一个可用的服务器,如此循环,直到所有服务器都不可用为止。

next-available:与first-available类似,新连接从目标列表路由到第一个可用服务器。与first-available不同的是,如果一个服务器被标记为不可访问,那么它将被丢弃,并且永远不会再次用作目标。重启Router后,所有被丢弃服务器将再次可选。此策略向后兼容MySQL Router 2.x中mode为read-write的行为。

        现在7002端口的路由策略为first-available,下面依次停止172.16.1.125:3306、172.16.1.126:3306、172.16.1.127:3306,观察7002端口的访问情况。


# 停止 172.16.1.125:3306

[mysql@hdp2~]$mysqladmin -uwxy -p123456 -h172.16.1.125 -P3306 shutdown

mysqladmin: [Warning] Using a password on the command line interface can be insecure.

[mysql@hdp2~]$

 

# 访问7002

[mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

+------------+

| @@hostname |

+------------+

| hdp3       |

+------------+

 

# 停止 172.16.1.126:3306

[mysql@hdp3~]$mysqladmin -uwxy -p123456 -h172.16.1.126 -P3306 shutdown

mysqladmin: [Warning] Using a password on the command line interface can be insecure.

[mysql@hdp3~]$

 

# 访问7002

[mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

+------------+

| @@hostname |

+------------+

| hdp4       |

+------------+

[mysql@hdp1~]$

 

# 停止 172.16.1.127:3306

[mysql@hdp4~]$mysqladmin -uwxy -p123456 -h172.16.1.127 -P3306 shutdown

mysqladmin: [Warning] Using a password on the command line interface can be insecure.

[mysql@hdp4~]$

 

# 启动172.16.1.125:3306

[mysql@hdp2~]$mysqld_safe --defaults-file=/etc/my.cnf &

 

# 访问7002

[mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

+------------+

| @@hostname |

+------------+

| hdp2       |

+------------+

[mysql@hdp1~]$

        first-available总是循环查找目标列表中第一个可用服务器并连接它。将7002的策略改为next-available,把上面的步骤再做一遍,会看到最后的查询失败。即使此时172.16.1.125:3306可用也不会再次连接它,除非重启Router。


# 最后的查询连接失败

[mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

ERROR 2003 (HY000): Can't connect to remote MySQL server for client connected to 'localhost:7002'

 

# 重启路由

[mysql@hdp1~]$kill `ps -ef | grep router | grep -v grep | awk '{print $2}'`

[mysql@hdp1~]$mysqlrouter -c ~/.mysqlrouter.conf &

 

# 再次查询

[mysql@hdp1~]$mysql -uwxy -p123456 -P7002 --protocol=TCP -e"select @@hostname"

Warning: Using a password on the command line interface can be insecure.

+------------+

| @@hostname |

+------------+

| hdp2       |

+------------+

[mysql@hdp1~]$

        可以在网络上的单台或多台主机上运行多个MySQL路由器实例,而无需将MySQL Router隔离到单个机器上。这是因为MySQL Router对任何特定服务器或主机都不具有亲和性。要停止MySQL Router,只需用kill或killall命令直接杀掉相关进程。MySQL Router只起到一个转发流量的作用,它实在太“轻”了,以至都没有一个单独的停止命令。


三、配置

        MySQL Router启动时可以从配置文件、扩展配置文件、命令行选项三个地方获取配置信息。本节说明MySQL Router配置文件的位置、配置文件语法和配置选项。


1. 配置文件位置

(1)缺省配置文件

        MySQL Router在启动时扫描缺省配置文件,并可选择在运行时从命令行加载用户定义的配置文件。默认情况下,MySQL Router扫描依赖于操作系统的特定位置以查找配置文件。执行mysqlrouter --help可以查看系统上的缺省配置文件位置:


[mysql@hdp1~]$mysqlrouter --help | more

MySQL Router  Ver 8.0.17 for linux-glibc2.12 on x86_64 (MySQL Community - GPL)

Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.

 

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

 

Configuration read from the following files in the given order (enclosed

in parentheses means not available for reading):

  (/home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/.././mysqlrouter.conf)

  (/home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/.././mysqlrouter.ini)

  /home/mysql/.mysqlrouter.conf

  (/home/mysql/.mysqlrouter.ini)

Plugins Path:

  /home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/lib/mysqlrouter

 

Default Log Directory:

  /home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64

 

Default Persistent Data Directory:

  /home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/../var/lib/mysqlrouter

 

Default Runtime State Directory:

  /home/mysql/mysql-router-8.0.17-linux-glibc2.12-x86_64/bin/../run

 

...

        从帮助信息的开始部分可以看到MySQL Router查找的缺省配置文件和查找顺序。括号中的文件不可用,这里只有/home/mysql/.mysqlrouter.conf一个可用缺省配置文件。注意,如果使用-c或--config选项传入用户定义的配置文件,则不会加载缺省配置文件。


(2)用户定义和扩展配置文件

        用户定义配置文件由-c或--config命令行选项指定,扩展配置文件由-a或--extra-config命令行选项指定。从缺省配置文件或使用--config选项指定的文件读取配置后,读取扩展配置文件:


shell> mysqlrouter --config /custom/path/to/router.conf --extra-config /another/config.conf

可以传入多个扩展配置选项,并按照输入的顺序加载文件:


shell> mysqlrouter --config b.conf --extra-config a.conf --extra-config c.conf

在上面的示例中,首先加载b.conf,然后按顺序加载a.conf和c.conf。此外由于使用了--config,不会加载缺省配置文件。每个加载的配置文件都会覆盖先前读取的配置文件中的设置。


2. 配置文件语法

        MySQL Router配置文件格式类似于MySQL服务器的配置文件,符合传统INI文件格式,其中包含多个段,每个段中包含多个选项。选项中的目录支持支持正斜杠和反斜杠,反斜杠无条件复制而不是转义字符。配置文件可以包含注释行,注释行以井号(#)或分号(;)开头,并继续到行尾。注意只支持整行注释,不支持行中、行尾注释。(1)段

每个配置文件都包含一个配置段列表,其中每个段包含一系列配置选项,每个配置选项都有名称和值,例如:


[section name]

option = value

option = value

option = value

 

[section name:optional section key]

option = value

option = value

option = value

        中括号中的是段名和可选的段键,段名与段键之间用冒号(:)分隔。段名和段键的组合对于配置是唯一的,中括号内不能有首尾空格。段名与段键由一个或多个字母、数字或下划线(_)的序列组成,不允许使用其它字符。


        段类似于命名空间。例如user选项,其含义取决于其关联的段。[DEFAULT]段中的user指的是运行MySQL Router的系统用户,该用户也受--user命令行选项控制。[metadata_cache]段中定义的user,指的是访问MySQL服务器元数据的MySQL用户。


        下面列举几个主要的段:


[DEFAULT]:DEFAULT是一个特殊的段,用于选项缺省值,在该段中查找其它段中没出现的选项,通常配置扩展配置文件的目录、日志的目录、MySQL Router运行时的目录(如pid文件)等。DEFAULT段不接受段键。

[logger]:logger段只有一个选项,设置日志的记录级别。

[routing:NAME]:该段是MySQL Router主要配置部分,设置不同的路由实例,其中NAME是自定义的段键名。

(2)选项


        在段名之后,可以有一个零或多个选项行,其中每个选项行的形式如下:


name = value

        处理之前将删除选项名称或选项值上的任何首尾空格。选项名称不区分大小写。选项值支持在大括号中引用选项名称,作为变量插入值。变量引用值是在检索选项值时完成的,而不是在读取配置文件时。如果变量未定义,则不进行替换,并按字面读取选项值。考虑下面的示例配置文件:


[DEFAULT]

prefix = /usr/

 

[sample]

bin = {prefix}bin/{name}

lib = {prefix}lib/{name}

name = magic

directory = /data/{mysqlrouterdata}

这里bin的值是“/usr/bin/magic”,lib的值是“/usr/lib/magic”。由于未定义名为“{mysqlrouterdata}”的变量,directory的值是“/data/{mysqlrouterdata}”。


        MySQL Router定义了配置文件可用的如下预定义变量。变量使用大括号,例如{program}作为Router可执行程序预定义变量。


program:程序的名称,通常是mysqlrouter。

origin:二进制文件所在目录。

logging_folder:日志文件所在目录。

plugin_folder:插件文件所在目录。

runtime_folder:运行时数据文件所在目录。

config_folder:配置文件所在目录。

3. 配置文件示例

        启动时,MySQL Router会读取配置文件列表,这些配置文件一起构成Router的配置。至少需要一个配置文件,否则启动Router时会报 Error: No valid configuration file available 错误。下面是一个名为mycluster的MySQL InnoDB cluster的基本连接路由示例,读写流量发送到6446端口,只读访问使用6447端口。


[DEFAULT]

logging_folder=/opt/routers/myrouter/log

runtime_folder=/opt/routers/myrouter/run

data_folder=/opt/routers/myrouter/data

connect_timeout=30

read_timeout=30

 

[logger]

level = INFO

 

[metadata_cache:mycluster]

router_id=5

bootstrap_server_addresses=mysql://localhost:3310,mysql://localhost:3320,mysql://localhost:3330

user=mysql_router

metadata_cluster=mycluster

ttl=5

 

[routing:mycluster_default_rw]

bind_address=0.0.0.0

bind_port=6446

destinations=metadata-cache://mycluster/default?role=PRIMARY

routing_strategy=round-robin

 

[routing:mycluster_default_ro]

bind_address=0.0.0.0

bind_port=6447

destinations=metadata-cache://mycluster/default?role=SECONDARY

routing_strategy=round-robin

        该配置中定义了五个段:


[DEFAULT]中定义了数据文件目录、日志文件目录、运行时文件目录的位置,以及连接和读取MySQL元数据服务器的超时时间为30秒。

[logger]中定义日志级别为info,可选值有info、debug、warning、error、fatal,不区分大小写。

[metadata_cache:mycluster]中定义MySQL服务器元数据访问信息:router_id是整型的路由ID。bootstrap_server_addresses是逗号分隔的InnoDB cluster中的MySQL实例。user定义访问元数据的用户。metadata_cluster定义InnoDB cluster名称。ttl定义缓存时间为5秒。

[routing:mycluster_default_rw]和[routing:mycluster_default_ro]分别定义读写路由和只读路由。bind_address指定路由使用本机IP地址。配置文件中的bind_address选项只接受一个地址,但是可以使用bind_addres = 0.0.0.0绑定到localhost上的所有地址。bind_port指定客户端连接Router使用的端口。destinations引用由metadata-cache定义的目标地址,以利用InnoDB Cluster的元数据缓存来动态配置主机信息。如果不使用InnoDB Cluster,destinations可以指定为逗号分隔的IP:port地址,但bind_address中的地址不能出现在destinations列表中。routing_strategy定义路由策略,本例中读写和只读均为循环访问三个节点。

        配置选项的完整说明,参见https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-conf-options.html。


        总的来说,MySQL Router从原理、安装、配置到部署使用都是如此轻而易举,可满足简单高可用应用场景的需求。









使用MySQL Router实现高可用、负载均衡、读写分离


一、MySQL Router简介

        MySQL Router是MySQL官方提供的一个轻量级中间件,可以在应用程序与MySQL服务器之间提供透明的路由方式。主要用以解决MySQL主从库集群的高可用、负载均衡、易扩展等问题。Router可以与MySQL Fabric无缝连接,允许Fabric存储和管理用于路由的高可用数据库服务器组,使管理MySQL服务器组更加简单。


        MySQL Router是一个可执行文件,可以与应用程序在同一平台上运行,也可以单独部署。虽然MySQL Router是InnoDB Cluster(MySQL 7.X)的一部分,MySQL 5.6 等版本数据库仍然可以使用Router作为其中间代理层。MySQL Router的配置文件中包含有关如何执行路由的信息。它与MySQL服务器的配置文件类似,也是由多个段组成,每个段中包含相关配置选项。


        MySQL Router是MySQL Proxy的替代方案,MySQL官方不建议将MySQL Proxy用于生产环境,并且已经不提供MySQL Proxy的下载。


1. 功能

        Router作为一个流量转发层,位于应用与MySQL服务器之间,其功能类似于LVS。MySQL Servers作为Router的“downstream”(NAT模式),应用不再直连MySQL Servers,而是与Router相连。根据Router的配置,将会把应用程序的读写请求转发给下游的MySQL Servers。


        当下游有多个MySQL Servers,无论主、从,Router可以对读写请求进行负载均衡。当下游某个Server失效时,Router可以将其从Active列表中移除,当其online后再次加入Active列表,即提供了Failover特性。


        当MySQL Servers集群拓扑变更时,比如增减Slaves节点,只需要修改Router的配置即可,无需修改应用中数据库连接配置,因为应用配置的为Router地址而非MySQL Servers的原始地址,即数据库集群对应用来说是透明的。如果MySQL Servers为5.7+版本,且构建为InnoDB Cluster模式,那么Router还能基于metaCache(metaServers)机制,感知MySQL Servers的主从切换、从库增减等集群拓扑变更,而且基于变更能够实现Master自动切换、Slaves列表自动装配等。比如Master失效后,Cluster将会自动选举一个新的Master,此时Router不需要任何调整、可以自动发现此新Master进而继续为应用服务。


        考虑到Router独立部署可能引入“额外的部署成本”、“性能降级”、“连接数上限”等问题,通常建议基于“Agent”方式部署,即将Router与应用部署在机器上。Router通常是解决“MySQL集群规模性迁移”,比如跨机房部署、流量迁移、异构兼容,或者解决MySQL集群规模性宕机时快速切换等。


        Router中间件本身不会对请求“拆包”(unpackage),所以无法在Router中间件上实现比如“SQL审计”、“隔离”、“限流”、“分库分表”等功能。但是Router提供了plugin(C语言)机制,用户可以开发自己的plugin来扩展Router的额外特性。


2. 架构

        MySQL Router是一个单独的应用程序,其体系结构如图1所示。


图1


       


        在图1的最左边是连接到Router的应用程序,最右侧是两个连接目的地,即MySQL Fabric和MySQL Cluster。中间的Router架构分为三层,从上至下依次为插件层、核心层和Harness。插件层是对应用开放的接口,mysqlrouter程序是Router的核心,而该程序时基于MySQL Harness实现的。Router采用模块化设计,并在实现功能时利用此架构。MySQL Harness是一个基础模块,提供日志、配置重载、插件管理等功能。当前Router提供Connection Routing和Fabric Cache两个插件,未来功能将与这两个插件一起出现。


        如图1中的箭头所示,应用程序连接Router,如果连接路由插件,Router从配置文件中读取目标并重定向到列表中的一个服务器。如果使用Fabric Cache,需在Router的路由策略中指定Fabric安装的URL。这种情况下,应用程序连接到Router,然后Router将从Fabric获取目标列表,然后将连接重定向到列表中的一个服务器。


3. 使用

        正如前面提到的,在目前形式中,MySQL Router最好与应用程序一起使用。也就是说,应该在运行应用程序的相同机器上安装Router。虽然这不是强制要求,但建议采用这种做法。可以编写程序来监控mysqlrouter的执行,并在需要时重新启动它。例如,如果目标选项中的服务器列表已用尽,则可以使用新目标列表重新启动Router,或重新启动Router以重试列表中的服务器。图2说明了如何在应用程序中使用Router。

图2


       


        可以在整个网络中运行多个Router实例。但是MySQL官方并没有提供Router集群的HA,即每个Router节点均为独立,它们之间互不通信,无Leader角色,无选举机制。那么当某个Router节点失效,应用层面需要借助MySQL Connector的高级特性,比如:failover、loadbalance等协议来实现Failover功能。简单而言,Router中间件与Connector的高级协议互相协作,才能够实现请求在Router集群之间的负载均衡、Failover等。


        MySQL Router非常轻量级,与直连Servers相比,其性能损耗低于1%。摆在Router面前的问题,是其对链接数的支撑能力,原则上我们一个Router节点限定在500个TCP链接。Router本身CPU、内存、磁盘消耗都极低,但是要求Router节点对网络IO的支撑能力应该较强。考虑到Router底层为“异步IO”,如果条件允许,应该构建在较高版本的Linux平台下,且给予合理的CPU资源。MySQL Router在2.1.4版本以下,内核基于select() IO模型,存在连接数500上限、较大SQL请求导致CPU过高,以及并发连接过高时Router假死等问题,建议升级到2.1.6+。


        Router对连接的管理是基于“粘性”方式,即应用与Router的一个TCP连接,将对应一个Router与MySQL Server的连接,当应用与Router的连接失效时,Router也将断开其与MySQL Server的连接。只要Router上下游网络联通性正常,那么Router将不会主动断开与应用的连接,也不会切换其与Server的连接。即当应用与Router创建一个新连接时,Router将根据负载均衡算法,选择一个Server并与其建立连接,此后将唯一绑定,直到此Server失效时触发重新选择其他Server。这就引入一个问题,如果某个连接上发生了“繁重”的SQL操作,那么将会导致下游Server伴随高负载而无法“负载均衡”。

    

        Router对应用是透明的,开发与Router一起使用的应用程序不需要任何特殊的库或接口,所增加的工作只是维护MySQL Router实例。


二、安装配置

        环境

172.16.1.125:MySQL Router

172.16.1.126:MySQL Replication Master 

172.16.1.127:MySQL Replication Slave


        我们在172.16.1.125上安装配置MySQL Router,172.16.1.126、172.16.1.127为本例中要通过Router访问的两个已经MySQL数据库服务器地址。在本例中这两个MySQL服务器已经配置好主从复制,拓扑如图3所示。

图3



1. 下载二进制安装包

        从https://dev.mysql.com/downloads/router/2.1.html页面选择下载的安装包,本例为mysql-router-2.1.6-linux-glibc2.12-x86-64bit.tar.gz。


2. 解压缩


tar xzf mysql-router-2.1.6-linux-glibc2.12-x86-64bit.tar.gz 

mv mysql-router-2.1.6-linux-glibc2.12-x86-64bit mysql-router-2.1.6

3. 在资源文件中(本例为.bashrc)添加执行文件路径

.bashrc文件的内容为:


[mysql@hdp2~]$more ~/.bashrc 

# .bashrc

 

# Source global definitions

if [ -f /etc/bashrc ]; then

    . /etc/bashrc

fi

 

# Uncomment the following line if you don't like systemctl's auto-paging feature:

# export SYSTEMD_PAGER=

 

# User specific aliases and functions

export PATH=.:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/home/mysql/mysql-5.6.14/bin:/home/mysql/mysql-router-2.1.6/bin;

[mysql@hdp2~]$

使资源配置生效:


source ~/.bashrc

4. 验证安装


[mysql@hdp2~]$mysqlrouter --help

MySQL Router v2.1.6 on Linux (64-bit) (GPL community edition)

Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.

 

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

 

Start MySQL Router.

 

Configuration read from the following files in the given order (enclosed

in parentheses means not available for reading):

  (/home/mysql/mysql-router-2.1.6/bin/.././mysqlrouter.conf)

  (/home/mysql/.mysqlrouter.conf)

Plugins Path:

  /home/mysql/mysql-router-2.1.6/lib/mysqlrouter

Default Log Directory:

  /home/mysql/mysql-router-2.1.6

Default Persistent Data Directory:

  /home/mysql/mysql-router-2.1.6/data

Default Runtime State Directory:

  /home/mysql/mysql-router-2.1.6/run

 

......

        从mysqlrouter联机帮助的输出中,可以看到默认配置文件寻找路径及其顺序,插件路径、日志目录、持久化数据目录、运行时状态目录的缺省位置等重要信息。在后面的配置文件和服务启停文件中需要定义这些目录。注意,如果在mysqlrouter命令行使用--config或-c选项传入用户定义的配置文件,则不会加载默认配置文件。


5. 配置Router


# 复制配置文件

cp /home/mysql/mysql-router-2.1.6/share/doc/mysqlrouter/sample_mysqlrouter.conf /etc/mysqlrouter.conf

cp /home/mysql/mysql-router-2.1.6/share/doc/mysqlrouter/sample_mysqlrouter.init /etc/init.d/mysqlrouter

 

# 修改属主为mysql

chown mysql:mysql /etc/mysqlrouter.conf

chown mysql:mysql /etc/init.d/mysqlrouter

 

# 变为可执行

chmod +x /etc/init.d/mysqlrouter

 

# 系统启动时自动执行

echo "/etc/init.d/mysqlrouter" >> /etc/rc.d/rc.local

 

# 建立日志目录

mkdir /home/mysql/mysql-router-2.1.6/log

         配置文件内容如下:


[mysql@hdp2~]$more /etc/mysqlrouter.conf

[DEFAULT]

# 日志路径

logging_folder = /home/mysql/mysql-router-2.1.6/log

 

# 插件路径

plugin_folder = /home/mysql/mysql-router-2.1.6/lib/mysqlrouter

 

# 配置路径

config_folder = /home/mysql/mysql-router-2.1.6/config

 

# 运行时状态路径

runtime_folder = /home/mysql/mysql-router-2.1.6/run

 

# 数据文件路径

data_folder = /home/mysql/mysql-router-2.1.6/data

 

[logger]

# 日志级别

level = INFO

 

# 以下选项可用于路由标识的策略部分

[routing:basic_failover]

# Router地址

bind_address = 172.16.1.125

# Router端口

bind_port = 7001

# 读写模式

mode = read-write

# 目标服务器

destinations = 172.16.1.126:3306,172.16.1.127:3306

 

[routing:load_balance]

bind_address = 172.16.1.125

bind_port = 7002

mode = read-only

destinations = 172.16.1.126:3306,172.16.1.127:3306

 

[mysql@hdp2~]$

        MySQL Router的配置文件比较简单,大部分配置项的含义一路了然。上面的文件中配置了两条路由策略,一个用于失败切换,一个用于负载均衡,绑定端口分别是7001和7002。值得一提的是mode参数,该参数的可选值为read-write或read-only,但其实际作用并不是字面含义所示。


        对于read-write模式,将采用“首个可用”算法,优先使用第一个server,当第一个server(即172.16.1.126:3306)不可达时,将会Failover到第二个server(172.16.1.127:3306),依次进行。如果都不可达,那么此端口上的请求将会被中断,此端口将不能提供服务,且此时所属的路由策略将不可用。需要注意,此算法只遍历一次列表,即逐个验证destinations中的Server,不会循环。一旦所有的Servers依次验证且不可用后,本条路由策略将不能继续服务,内置状态设定为aborted,即使此后Servers恢复上线,也不能继续对Client提供服务,因为它不会与Servers保持心跳检测。对于Router而言,直接拒绝Client连接请求,只有重启Router节点才能解决。


        对于read-only模式:将采用“轮询”算法,依次选择Server新建连接,如果某个Server不可达,将会重试下一个Server,如果所有的Server都不可达,那么此端口上的请求将中断,即读写操作将不可用。同时Router将会持续与每个Server保持心跳探测,当恢复后重新加入Active列表,此后那些新建连接请求将可以分发给此Server。


        但是比较遗憾,Router不会将已有的连接重新分配给“新加入”列表的Server,比如Router有2个Server地址(S1,S2),某时刻S1不可达,那么在S1上粘性的客户端连接也将被断开,新建连接将会全部在S2上,此后S1恢复正常,那么在S2上的旧的连接将不会迁移到S1上,此时S1只会接收新的连接,如果没有新连接请求,那么S1将会在一段时间看起来是“不提供服务”的。为了解决此问题,我们要求Connection Pool有管理“连接生命周期”的相关控制,比如一个connection被创建X秒以后在返回连接池时应该被主动关闭,这个参数在tomcat-jdbc-pool中为“maxAge”。        如果应用程序中,部署方式是单Master、多Slaves,我们完全可以在承接“master”请求的Router节点上,也配置为“read-only”模式,那么此单master节点失效重启后,可以不需要重启Router节点即可继续服务。因为Router不会对TPC拆包,所有“read-write”、“read-only”并不会干扰实际的SQL执行。严格来说,这两种mode映射两种“路由算法”:“首个可用”、“轮询”;除此之外,再无特殊含义。

    

        对于读写两种操作,因为Router不对请求拆包,所以它无法判断请求的读写类型。我们只能在配置文件中,分别为读、写设定不同的配置:使用不同的绑定端口。比如本例“7001”端口接收到的请求都会转发给172.16.1.126:3306,当它不可用时,都会转发给172.16.1.127:3306。“7002”端口接收的请求则会轮询转发给172.16.1.126:3306和172.16.1.127:3306。

    

        MySQL Router服务启停文件内容如下:


[mysql@hdp2~]$more /etc/init.d/mysqlrouter

#! /bin/bash

#

# mysqlrouter This shell script takes care of starting and stopping

# the MySQL Router

#

# chkconfig: 2345 66 34

# description: MySQL Router

# processname: mysqlrouter

# config: /etc/mysqlrouter/mysqlrouter.ini

# pidfile: /var/run/mysqlrouter/mysqlrouter.pid

#

# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.

#

# This program is free software; you can redistribute it and/or modify

# it under the terms of the GNU General Public License as published by

# the Free Software Foundation; version 2 of the License.

#

# This program is distributed in the hope that it will be useful,

# but WITHOUT ANY WARRANTY; without even the implied warranty of

# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

# GNU General Public License for more details.

#

# You should have received a copy of the GNU General Public License

# along with this program; if not, write to the Free Software

# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

 

#

# Maintainer: MySQL Release Engineering <mysql-build@oss.oracle.com>

#

 

# Source function library

. /etc/rc.d/init.d/functions

 

# Source networking configuration

. /etc/sysconfig/network

 

# add general install path

base_dir=/home/mysql/mysql-router-2.1.6

# fix exec path

exec=${base_dir}/bin/mysqlrouter

prog=mysqlrouter

piddir=${base_dir}/run

pidfile=${piddir}/mysqlrouter.pid

logdir=${base_dir}/log

logfile=$logdir/mysqlrouter.log

lockfile=/var/lock/subsys/$prog

 

# add conf path

conf=/etc/mysqlrouter.conf

 

start () {

[ -d $piddir ] || mkdir -p $piddir

chown mysql:mysql $piddir

[ -d $logdir ] || mkdir -p $logdir

chown mysql:mysql $logdir

[ -e $logfile ] || touch $logfile

chown mysql:mysql $logfile

export ROUTER_PID=$pidfile

# add opt -c to resolv mysqlrouter.ini

daemon --user mysql $exec -c $conf >/dev/null 2>&1 &              #

ret=$?

if [ $ret -eq "0" ]; then

action $"Starting $prog: " /bin/true

touch /var/lock/subsys/$prog

else

action $"Starting $prog: " /bin/false

fi

return $ret

}

 

stop () {

[ -f /var/lock/subsys/$prog ] || return 0

killproc mysqlrouter >/dev/null 2>&1

ret=$?

if [ $ret -eq "0" ]; then

rm -f $pidfile

rm -f /var/lock/subsys/$prog

action $"Stopping $prog: " /bin/true

else

ation $"Stopping $prog: " /bin/false

fi

}

 

restart () {

stop

start

}

 

condrestart () {

[ -e /var/lock/subsys/$prog ] && restart || return 0

}

 

case "$1" in

start)

start

;;

stop)

stop

;;

status)

status -p "$pidfile" $prog

;;

restart)

restart

;;

condrestart|try-restart)

condrestart

;;

reload)

exit 3

;;

force-reload)

restart

;;

*)

echo $"Usage: $0 {start|stop|status|condrestart|try-restart|reload|force-reload}"

exit 2

esac

 

exit $?

[mysql@hdp2~]$ 

        当程序意外被KILL后,有相关程序运行标识,需要先:


rm -f $pidfile

rm -f /var/lock/subsys/$prog

        再启动,否则程序会提示有一个实例运行而不能运行该服务。


        很多程序需要判断是否当前已经有一个实例在运行,这个目录就是让程序判断是否有实例运行的标志。比如说xinetd,如果存在这个文件,表示已经有xinetd在运行了,否则就是没有。当然程序里面还要有相应的判断措施来真正确定是否有实例在运行。通常与该目录配套的还有/var/run目录,用来存放对应实例的PID,如果写脚本的话,会发现这2个目录结合起来可以很方便的判断出许多服务是否在运行,运行的相关信息等等。实际上,判断是否上锁就是判断这个文件,所以文件存在与否也就隐含了是否上锁。而这个目录的内容并不能表示一定上锁了,因为很多服务在启动脚本里用touch来创建这个加锁文件,在系统结束时该脚本负责清除锁,这本身就不可靠,比如意外失败导致锁文件仍然存在。所以脚本里一般结合PID文件,如果有PID文件的话,从PID文件里得到该实例的PID,然后用ps测试是否存在该PID,从而判断是否真正有这个实例在运行,更加稳妥的方法是用进程通讯,不过这样的话单单靠脚本就做不到了。6. 启动Router服务

        用root用户执行服务启动命令:


[root@hdp2~]#service mysqlrouter start

Starting mysqlrouter (via systemctl):                      [  OK  ]

[root@hdp2~]#

        查看日志文件,显示两个路由策略的监听器已经启动。


[mysql@hdp2~]$more /home/mysql/mysql-router-2.1.6/log/mysqlrouter.log 

2018-07-18 17:04:11 INFO    [7fa3437fb700] [routing:load_balance] started: listening on 172.16.1.125:7002; read-only

2018-07-18 17:04:11 INFO    [7fa343ffc700] [routing:basic_failover] started: listening on 172.16.1.125:7001; read-write

[mysql@hdp2~]$

        如果在启动服务时出现类似 log_daemon_msg: command not found 这样的错误,按如下步骤处理。


安装redhat-lsb-core。

yum -y install redhat-lsb-core

编辑/usr/lib/lsb/init-functions文件,在文件最后添加如下内容。

log_daemon_msg () {

    # Dummy function to be replaced by LSB library.

 

    echo $@

}

log_progress_msg() {

   echo $@

}

log_end_msg () {

    # Dummy function to be replaced by LSB library.

 

    if test "$1" != "0"; then

      echo "Error with $DESCRIPTION: $NAME"

    fi

    return $1

}

 


三、自动失败切换

        当172.16.1.126可用时,对于7001端口的请求,会全部发送到172.16.1.126。对7002端口的请求,会轮询发送给172.16.1.126和172.16.1.127。


C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7001 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7001 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 127   |

+---------------+-------+

        当172.16.1.126不可用时,对于7001端口的请求,会自动切换到172.16.1.127,而对于7002端口的请求,会全部转移到172.16.1.127。


        杀掉172.16.1.126的进程:


pkill -9 mysqld

        查看路由的目标服务器:


C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7001 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 127   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7001 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 127   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 127   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 127   |

+---------------+-------+

        当172.16.1.126再次可用时(假设复制已经重新搭建,主从角色已经互换,172.16.1.127为master,172.16.1.126为slave),对于7001端口的请求,还是会路由到172.16.1.127,而不会自动转到172.16.1.126。而对于7002端口的请求,会自动继续轮询发送给172.16.1.126、172.16.1.127两个服务器。


        启动172.16.1.126的mysql服务:


service mysql start

        查看路由的目标服务器:


C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7001 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 127   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7001 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 127   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 127   |

+---------------+-------+

        此时重启mysqlrouter服务,回到初始状态,对于7001端口的请求,只会路由到172.16.1.126。对7002端口的请求路由策略不变,会轮询发送给172.16.1.126和172.16.1.127。


        在172.16.1.125上重启mysqlrouter服务:


service mysqlrouter restart

        查看路由的目标服务器:


C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7001 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7001 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "show variables like 'server_id'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 127   |

+---------------+-------+

        注意,此时172.16.1.126在复制中的角色依然是slave,但只有它接受读写请求,实际上是以172.16.1.126作为复制的master,这次Router的重启已经破坏了复制的数据一致性,因此这种情况下需要重新手工搭建复制互换角色。


C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7001 -e "use test; create table t1 (a int); insert into t1 values (1);"

mysql: [Warning] Using a password on the command line interface can be insecure.

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "show variables like 'server_id';select * from test.t1;"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

+------+

| a    |

+------+

|    1 |

+------+

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "show variables like 'server_id';select * from test.t1;"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 127   |

+---------------+-------+

ERROR 1146 (42S02) at line 1: Table 'test.t1' doesn't exist

 

验证read-only模式下的写请求:

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "insert into test.t1 values (2);"

mysql: [Warning] Using a password on the command line interface can be insecure.

 

C:\WINDOWS\system32>mysql -utest -p123456 -h172.16.1.125 -P7002 -e "show variables like 'server_id';select * from test.t1;"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

+------+

| a    |

+------+

|    1 |

|    2 |

+------+

四、负载均衡

        从上面的实验可以看出,在一主一从的配置中,只要将读请求发送到7002端口,请求会被轮询发送到两个MySQL服务器,从而达到读负载均衡的目的。对于读写负载均衡,则需要配置双主复制,然后将两个MySQL服务器都放到read-only下,例如两台MySQL服务器互为主从的拓扑结构,只需要配置如下一条路由策略即可。


[routing:load_balance]

bind_address = 172.16.1.125

bind_port = 7001

mode = read-only

destinations = 172.16.1.126:3306,172.16.1.127:3306

        虽然叫read-only模式,但这只是指出路由方式为“轮询”。正如上面测试看到的,两个服务器会以轮询方式进行读写,也就实现了最简单读写负载均衡。


五、读写分离

        从上面的实验可以看出,在一主一从的配置中,只要将写请求发送到7001端口,读请求7002端口,就可实现读写分离。正常情况下,master接收写请求,master和slave接收读请求。如果master宕机,所有读写请求都切换到slave一台服务器上。


六、多实例

1. 环境

172.16.1.125:3306、3307两个端口对应两个MySQL实例,均为master;MySQL Router;绑定VIP 172.16.1.100。

172.16.1.126:3306、3307端口对应两个MySQL实例,分别是172.16.1.125上3306、3307两个MySQL实例的slave。


2. 配置文件

[root@hdp2/data2]#more /etc/mysqlrouter.conf 

[DEFAULT]

logging_folder = /home/mysql/mysql-router-2.1.6/log

plugin_folder = /home/mysql/mysql-router-2.1.6/lib/mysqlrouter

config_folder = /home/mysql/mysql-router-2.1.6/config

runtime_folder = /home/mysql/mysql-router-2.1.6/run

data_folder = /home/mysql/mysql-router-2.1.6/data

 

[logger]

level = INFO

 

[routing:db1_write]

bind_address = 172.16.1.100

bind_port = 33060

mode = read-write

destinations = 172.16.1.125:3306,172.16.1.126:3306

 

[routing:db1_read]

bind_address = 172.16.1.100

bind_port = 33061

mode = read-only

destinations = 172.16.1.126:3306

 

[routing:db2_write]

bind_address = 172.16.1.100

bind_port = 33070

mode = read-write

destinations = 172.16.1.125:3307,172.16.1.126:3307

 

[routing:db2_read]

bind_address = 172.16.1.100

bind_port = 33071

mode = read-only

destinations = 172.16.1.126:3307

3. 功能测试

(1)在172.16.1.125上绑定VIP


/sbin/ifconfig ens32:1 172.16.1.100

(2)客户端用VIP访问数据库


C:\WINDOWS\system32>mysql -uroot -p123456 -P33060 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 125   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3306  |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -uroot -p123456 -P33061 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3306  |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -uroot -p123456 -P33070 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 125   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3307  |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -uroot -p123456 -P33071 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3307  |

+---------------+-------+

 

C:\WINDOWS\system32>

(3)停止两个master


mysqladmin -uroot -p123456 -P3306 -h127.0.0.1 shutdown

mysqladmin -uroot -p123456 -P3307 -h127.0.0.1 shutdown

(4)客户端用VIP访问数据库


C:\WINDOWS\system32>mysql -uroot -p123456 -P33060 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3306  |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -uroot -p123456 -P33061 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3306  |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -uroot -p123456 -P33070 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3307  |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -uroot -p123456 -P33071 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3307  |

+---------------+-------+

 

C:\WINDOWS\system32>

(5)重新启动两个master


mysqld_safe --defaults-file=/home/mysql/mysql-5.6.14/my.cnf &

mysqld_safe --defaults-file=/home/mysql/mysql-5.6.14/my_2.cnf &

(6)重启MySQL Router


service mysqlrouter restart

(7)客户端用VIP访问数据库


C:\WINDOWS\system32>mysql -uroot -p123456 -P33060 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 125   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3306  |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -uroot -p123456 -P33061 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3306  |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -uroot -p123456 -P33070 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 125   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3307  |

+---------------+-------+

 

C:\WINDOWS\system32>mysql -uroot -p123456 -P33071 -h172.16.1.100 -e "show variables like 'server_id'; show variables like 'port'"

mysql: [Warning] Using a password on the command line interface can be insecure.

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| server_id     | 126   |

+---------------+-------+

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| port          | 3307  |

+---------------+-------+

 

C:\WINDOWS\system32>

 


参考:

MySQL Router架构实践

mysql router 自动failover测试







About Me

........................................................................................................................

● 本文作者:小麦苗,部分内容整理自网络,若有侵权请联系小麦苗删除

● 本文在itpub、博客园、CSDN和个人微 信公众号( xiaomaimiaolhr)上有同步更新

● 本文itpub地址: http://blog.itpub.net/26736162

● 本文博客园地址: http://www.cnblogs.com/lhrbest

● 本文CSDN地址: https://blog.csdn.net/lihuarongaini

● 本文pdf版、个人简介及小麦苗云盘地址: http://blog.itpub.net/26736162/viewspace-1624453/

● 数据库笔试面试题库及解答: http://blog.itpub.net/26736162/viewspace-2134706/

● DBA宝典今日头条号地址: http://www.toutiao.com/c/user/6401772890/#mid=1564638659405826

........................................................................................................................

● QQ群号: 230161599 、618766405

● 微 信群:可加我微 信,我拉大家进群,非诚勿扰

● 联系我请加QQ好友 646634621 ,注明添加缘由

● 于 2020-02-01 06:00 ~ 2020-02-31 24:00 在西安完成

● 最新修改时间:2020-02-01 06:00 ~ 2020-02-31 24:00

● 文章内容来源于小麦苗的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解

● 版权所有,欢迎分享本文,转载请保留出处

........................................................................................................................

小麦苗的微店https://weidian.com/s/793741433?wfr=c&ifr=shopdetail

小麦苗出版的数据库类丛书http://blog.itpub.net/26736162/viewspace-2142121/

小麦苗OCP、OCM、高可用网络班http://blog.itpub.net/26736162/viewspace-2148098/

小麦苗腾讯课堂主页https://lhr.ke.qq.com/

........................................................................................................................

使用 微 信客户端扫描下面的二维码来关注小麦苗的微 信公众号( xiaomaimiaolhr)及QQ群(DBA宝典)、添加小麦苗微 信, 学习最实用的数据库技术。

........................................................................................................................

欢迎与我联系

 

 



来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26736162/viewspace-2677517/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
QQ:646634621| 网名:小麦苗| 微信公众号:xiaomaimiaolhr| 11g OCM| QQ群:618766405 微信群:私聊| 《数据库笔试面试宝典》作者| OCP、OCM、高可用(RAC+DG+OGG)网络班开讲啦,有需要的小伙伴可以私聊我。

注册时间:2012-09-23

  • 博文量
    1432
  • 访问量
    8513642