暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

GreatSQL用户实践四:利用MySQL Router实现读写分离

原创 Tonyhacks 2024-10-12
61

MySQL Router是MySQL官方提供的一个轻量级中间件,它在应用程序与MySQL服务器之间提供透明的路由服务。

MySQL Router主要功能

  1. 负载均衡:MySQL Router能够分析前端应用的请求,并将其转发给后端DB服务器处理,从而实现数据库的负载均衡。这有助于在多个数据库服务器之间分配负载,提高系统的整体性能和响应速度。
  2. 高可用性和故障转移:MySQL Router支持高可用性和故障转移功能。当集群中的某个MySQL服务器发生故障时,Router会自动将应用程序的连接转移到其他可用的数据库服务器上,确保业务连续性。
  3. 读写分离:MySQL Router支持读写分离功能,可以根据配置将读请求和写请求分发到不同的数据库服务器上。这有助于提高系统的读性能和写性能,并减少单个服务器的负载。
  4. 透明性:对前端应用层来说,MySQL Router是透明的。应用层不需要知道Router的存在,也不需要修改代码来适应Router。应用层只需将MySQL Router当作一个正常的MySQL实例来使用即可。

下载MySQL Router

wget https://downloads.mysql.com/archives/get/p/41/file/mysql-router-community-8.0.37-1.el8.x86_64.rpm
复制

安装MySQL Router

[root@GreatSQL01 bin]# rpm -ivh mysql-router-community-8.0.37-1.el8.x86_64.rpm warning: mysql-router-community-8.0.37-1.el8.x86_64.rpm: Header V4 RSA/SHA256 Signature, key ID a8d3785c: NOKEY Verifying... ################################# [100%] Preparing... ################################# [100%] Updating / installing... 1:mysql-router-community-8.0.37-1.e################################# [100%]
复制

初始化MySQL Router

MySQL Router第一次启动时要先初始化

参数解释参数 :

--bootstrap 表示开始初始化参数

GreatSQL@192.168.116.41:3306 是MGR服务专用账号

--user=mysqlrouter 是运行mysqlrouter进程的系统用户名

[root@GreatSQL01 bin]# mysqlrouter --bootstrap GreatSQL@192.168.116.41:3306 --user=mysqlrouter Please enter MySQL password for GreatSQL: # Bootstrapping system MySQL Router 8.0.37 (MySQL Community - GPL) instance... - Creating account(s) (only those that are needed, if any) - Verifying account (using it to run SQL queries that would be run by Router) - Storing account in keyring - Adjusting permissions of generated files - Creating configuration /etc/mysqlrouter/mysqlrouter.conf Existing configuration backed up to '/etc/mysqlrouter/mysqlrouter.conf.bak' # MySQL Router configured for the InnoDB Cluster 'MGR1' After this MySQL Router has been started with the generated configuration $ /etc/init.d/mysqlrouter restart or $ systemctl start mysqlrouter or $ mysqlrouter -c /etc/mysqlrouter/mysqlrouter.conf InnoDB Cluster 'MGR1' can be reached by connecting to: ## MySQL Classic protocol - Read/Write Connections: localhost:6446 - Read/Only Connections: localhost:6447 ## MySQL X protocol - Read/Write Connections: localhost:6448 - Read/Only Connections: localhost:6449
复制

如果想自定义名字和目录,还可以在初始化时自行指定 --name--directory 选项,这样可以实现在同一个服务器上部署多个Router实例。

启动MySQL Router

[root@GreatSQL01 ~]# systemctl start mysqlrouter [root@GreatSQL01 ~]# ps -ef | grep mysqlrouter mysqlro+ 40655 1 1 08:29 ? 00:00:00 /usr/bin/mysqlrouter root 40684 40627 0 08:29 pts/0 00:00:00 grep --color=auto mysqlrouter [root@GreatSQL01 ~]# netstat -lntp | grep mysqlrouter tcp 0 0 0.0.0.0:6449 0.0.0.0:* LISTEN 40655/mysqlrouter tcp 0 0 0.0.0.0:8443 0.0.0.0:* LISTEN 40655/mysqlrouter tcp 0 0 0.0.0.0:6446 0.0.0.0:* LISTEN 40655/mysqlrouter tcp 0 0 0.0.0.0:6447 0.0.0.0:* LISTEN 40655/mysqlrouter tcp 0 0 0.0.0.0:6448 0.0.0.0:* LISTEN 40655/mysqlrouter [root@GreatSQL01 ~]#
复制

可以看到 mysqlrouter 服务正常启动了。

解读MySQL Router配置文件

mysqlrouter 初始化时自动生成的配置文件是 /etc/mysqlrouter/mysqlrouter.conf,主要是关于R/W、RO不同端口的配置,例如:

[root@GreatSQL01 ~]# cat /etc/mysqlrouter/mysqlrouter.conf # File automatically generated during MySQL Router bootstrap [DEFAULT] name=system #定义了这个配置文件的名称为“system”。 user=mysqlrouter #指定运行MySQL Router的用户为“mysqlrouter”。 keyring_path=/var/lib/mysqlrouter/keyring #定义了密钥环的存储路径。 master_key_path=/etc/mysqlrouter/mysqlrouter.key #指定了主密钥文件的路径。 connect_timeout=5 #设置了连接超时时间为5秒。 read_timeout=30 #设置了读取超时时间为30秒。 dynamic_state=/var/lib/mysqlrouter/state.json #定义了动态状态信息的存储路径。 client_ssl_cert=/var/lib/mysqlrouter/router-cert.pem #指定了客户端SSL证书的路径。 client_ssl_key=/var/lib/mysqlrouter/router-key.pem #指定了客户端SSL密钥的路径。 client_ssl_mode=PREFERRED #设置了客户端SSL模式为“PREFERRED”,表示优先使用SSL连接。 server_ssl_mode=AS_CLIENT #设置了服务器SSL模式为“AS_CLIENT”,表示服务器的SSL设置与客户端一致。 server_ssl_verify=DISABLED #禁用了服务器SSL验证。 unknown_config_option=error #当遇到未知的配置选项时,将其视为错误。 [logger] level=INFO #设置了日志级别为“INFO”。 [metadata_cache:bootstrap] cluster_type=gr #指定集群类型为Group Replication。 router_id=1 #为Router指定了一个唯一标识符。 user=mysql_router1_pzoskfc3eb5l #用于连接MySQL服务器的用户。 metadata_cluster=MGR1 #指定了元数据集群的名称。 ttl=0.5 #设置了元数据缓存的生存时间(TTL)为0.5秒。 auth_cache_ttl=-1 #设置了认证缓存的TTL auth_cache_refresh_interval=2 #设置了认证缓存的刷新间隔。 use_gr_notifications=0 #禁用了对Group Replication通知的使用。 [routing:bootstrap_rw] #配置MySQL传统连接读写 bind_address=0.0.0.0 #绑定了所有可用的网络接口。 bind_port=6446 #指定了Router监听的端口。 destinations=metadata-cache://MGR1/?role=PRIMARY #定义了目标MySQL服务器的位置,使用了metadata-cache协议。 routing_strategy=first-available #设置了路由策略,如“first-available”和“round-robin-with-fallback”。 protocol=classic #指定了使用的协议,如“classic”和“x”。 [routing:bootstrap_ro] #配置MySQL传统连接只读 bind_address=0.0.0.0 #绑定了所有可用的网络接口。 bind_port=6447 #指定了Router监听的端口。 destinations=metadata-cache://MGR1/?role=SECONDARY #定义了目标MySQL服务器的位置,使用了metadata-cache协议。 routing_strategy=round-robin-with-fallback #设置了路由策略,如“first-available”和“round-robin-with-fallback”。 protocol=classic #指定了使用的协议,如“classic”和“x”。 [routing:bootstrap_x_rw] #配置MySQL X协议读写 bind_address=0.0.0.0 #绑定了所有可用的网络接口。 bind_port=6448 #指定了Router监听的端口。 destinations=metadata-cache://MGR1/?role=PRIMARY #定义了目标MySQL服务器的位置,使用了metadata-cache协议。 routing_strategy=first-available #设置了路由策略,如“first-available”和“round-robin-with-fallback”。 protocol=x #指定了使用的协议,如“classic”和“x”。 [routing:bootstrap_x_ro] #配置MySQL X协议只读 bind_address=0.0.0.0 #绑定了所有可用的网络接口。 bind_port=6449 #指定了Router监听的端口。 destinations=metadata-cache://MGR1/?role=SECONDARY #定义了目标MySQL服务器的位置,使用了metadata-cache协议。 routing_strategy=round-robin-with-fallback #设置了路由策略,如“first-available”和“round-robin-with-fallback”。 protocol=x #指定了使用的协议,如“classic”和“x”。 [http_server] #定义了HTTP服务器的配置 port=8443 #设置了HTTP服务器监听的端口。 ssl=1 #启用了SSL。 ssl_cert=/var/lib/mysqlrouter/router-cert.pem #指定了SSL证书的路径 ssl_key=/var/lib/mysqlrouter/router-key.pem #指定了SSL密钥的路径 [http_auth_realm:default_auth_realm] #http认证配置 backend=default_auth_backend method=basic name=default_realm [rest_router] require_realm=default_auth_realm [rest_api] [http_auth_backend:default_auth_backend] backend=metadata_cache [rest_routing] require_realm=default_auth_realm [rest_metadata_cache] require_realm=default_auth_realm [root@GreatSQL01 ~]#
复制

可以根据需要自行修改绑定的IP地址和端口,也可以在初始化时指定 --conf-base-port 选项自定义初始端口号。

确认读写分离效果

通过登录MySQL Router的6446端口看是否能登录MGR集群的primary节点

[root@GreatSQL01 ~]# mysql -h192.168.116.41 -u GreatSQL -p -P6446 Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 61089 Server version: 8.0.32-26 GreatSQL, Release 26, Revision a68b3034c3d Copyright (c) 2021-2024 GreatDB Software Co., Ltd Copyright (c) 2009-2024 Percona LLC and/or its affiliates Copyright (c) 2000, 2024, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. (Sat Oct 12 16:29:16 2024)[GreatSQL@GreatSQL][(none)]>SELECT MEMBER_ID,MEMBER_ROLE FROM performance_schema.replication_group_members; +--------------------------------------+-------------+ | MEMBER_ID | MEMBER_ROLE | +--------------------------------------+-------------+ | 20121e3a-7e37-11ef-9e5a-000c296335ba | PRIMARY | | 5fa2fefd-7e37-11ef-9e13-000c2927509d | SECONDARY | | 6f8dd4a8-7e37-11ef-bf56-000c29807526 | SECONDARY | +--------------------------------------+-------------+ 3 rows in set (0.00 sec) (Sat Oct 12 16:29:36 2024)[GreatSQL@GreatSQL][(none)]>SELECT @@server_uuid; +--------------------------------------+ | @@server_uuid | +--------------------------------------+ | 20121e3a-7e37-11ef-9e5a-000c296335ba | +--------------------------------------+ 1 row in set (0.00 sec) (Sat Oct 12 16:29:48 2024)[GreatSQL@GreatSQL][(none)]>
复制

通过登录MySQL Router的6447端口看是否能登录MGR集群的SECONDARY节点

[root@GreatSQL01 ~]# mysql -h192.168.116.41 -u GreatSQL -p -P6447 Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 252 Server version: 8.0.32-26 GreatSQL, Release 26, Revision a68b3034c3d Copyright (c) 2021-2024 GreatDB Software Co., Ltd Copyright (c) 2009-2024 Percona LLC and/or its affiliates Copyright (c) 2000, 2024, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. (Sat Oct 12 16:37:21 2024)[GreatSQL@GreatSQL][(none)]>SELECT MEMBER_ID,MEMBER_ROLE FROM performance_schema.replication_group_members; +--------------------------------------+-------------+ | MEMBER_ID | MEMBER_ROLE | +--------------------------------------+-------------+ | 20121e3a-7e37-11ef-9e5a-000c296335ba | PRIMARY | | 5fa2fefd-7e37-11ef-9e13-000c2927509d | SECONDARY | | 6f8dd4a8-7e37-11ef-bf56-000c29807526 | SECONDARY | +--------------------------------------+-------------+ 3 rows in set (0.08 sec) (Sat Oct 12 16:37:44 2024)[GreatSQL@GreatSQL][(none)]>SELECT @@server_uuid; +--------------------------------------+ | @@server_uuid | +--------------------------------------+ | 5fa2fefd-7e37-11ef-9e13-000c2927509d | +--------------------------------------+ 1 row in set (0.01 sec) (Sat Oct 12 16:37:55 2024)[GreatSQL@GreatSQL][(none)]>
复制

确认只读负载均衡效果

MySQL Router连接读写节点(Primary节点)默认的策略是 first-available,即只连接第一个可用的节点。Router连接只读节点(Secondary节点)默认的策略是 round-robin-with-fallback,会在各个只读节点间轮询。

保持6447端口原有的连接不退出,继续新建到6447端口的连接,查看 server_uuid,这时应该会发现读取到的是其他只读节点的值,因为 mysqlrouter 的读负载均衡机制是在几个只读节点间自动轮询。在默认的 round-robin-with-fallback 策略下,只有当所有只读节点都不可用时,只读请求才会打到PRIMARY节点上。

确认故障自动转移功能

接下来模拟PRIMARY节点宕机或切换时,mysqlrouter 也能实现自动故障转移。

先通过MySQL Router登录primary节点

[root@GreatSQL01 ~]# mysql -h192.168.116.41 -u GreatSQL -p -P6446 Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 62874 Server version: 8.0.32-26 GreatSQL, Release 26, Revision a68b3034c3d Copyright (c) 2021-2024 GreatDB Software Co., Ltd Copyright (c) 2009-2024 Percona LLC and/or its affiliates Copyright (c) 2000, 2024, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. (Sat Oct 12 16:43:20 2024)[GreatSQL@GreatSQL][(none)]>SELECT MEMBER_ID,MEMBER_ROLE FROM performance_schema.replication_group_members; +--------------------------------------+-------------+ | MEMBER_ID | MEMBER_ROLE | +--------------------------------------+-------------+ | 20121e3a-7e37-11ef-9e5a-000c296335ba | PRIMARY | | 5fa2fefd-7e37-11ef-9e13-000c2927509d | SECONDARY | | 6f8dd4a8-7e37-11ef-bf56-000c29807526 | SECONDARY | +--------------------------------------+-------------+ 3 rows in set (0.01 sec) (Sat Oct 12 16:44:01 2024)[GreatSQL@GreatSQL][(none)]>SELECT @@server_uuid; +--------------------------------------+ | @@server_uuid | +--------------------------------------+ | 20121e3a-7e37-11ef-9e5a-000c296335ba | +--------------------------------------+ 1 row in set (0.00 sec)
复制

重启primary节点GreatSQL

systemctl restart greatsql
复制

查看重启primary节点GreatSQL过程中,刚刚连接信息的变化

(Sat Oct 12 16:44:07 2024)[GreatSQL@GreatSQL][(none)]>SELECT MEMBER_ID,MEMBER_ROLE FROM performance_schema.replication_group_members; ERROR 2013 (HY000): Lost connection to MySQL server during query No connection. Trying to reconnect... Connection id: 287 Current database: *** NONE *** +--------------------------------------+-------------+ | MEMBER_ID | MEMBER_ROLE | +--------------------------------------+-------------+ | 5fa2fefd-7e37-11ef-9e13-000c2927509d | PRIMARY | | 6f8dd4a8-7e37-11ef-bf56-000c29807526 | SECONDARY | +--------------------------------------+-------------+ 2 rows in set (0.30 sec) (Sat Oct 12 16:45:00 2024)[GreatSQL@GreatSQL][(none)]>SELECT MEMBER_ID,MEMBER_ROLE FROM performance_schema.replication_group_members; +--------------------------------------+-------------+ | MEMBER_ID | MEMBER_ROLE | +--------------------------------------+-------------+ | 5fa2fefd-7e37-11ef-9e13-000c2927509d | PRIMARY | | 6f8dd4a8-7e37-11ef-bf56-000c29807526 | SECONDARY | +--------------------------------------+-------------+ 2 rows in set (0.00 sec) (Sat Oct 12 16:45:12 2024)[GreatSQL@GreatSQL][(none)]>SELECT MEMBER_ID,MEMBER_ROLE FROM performance_schema.replication_group_members; +--------------------------------------+-------------+ | MEMBER_ID | MEMBER_ROLE | +--------------------------------------+-------------+ | 20121e3a-7e37-11ef-9e5a-000c296335ba | SECONDARY | | 5fa2fefd-7e37-11ef-9e13-000c2927509d | PRIMARY | | 6f8dd4a8-7e37-11ef-bf56-000c29807526 | SECONDARY | +--------------------------------------+-------------+ 3 rows in set (0.00 sec) (Sat Oct 12 16:45:18 2024)[GreatSQL@GreatSQL][(none)]>SELECT @@server_uuid; +--------------------------------------+ | @@server_uuid | +--------------------------------------+ | 5fa2fefd-7e37-11ef-9e13-000c2927509d | +--------------------------------------+ 1 row in set (0.00 sec) (Sat Oct 12 16:52:31 2024)[GreatSQL@GreatSQL][(none)]>
复制

这就实现了自动故障转移。

至此,利用MySQL Router配合GreatSQL构建一套支持读写分离、读负载均衡以及故障自动转移的MGR集群就部署完毕了。

参考文章链接:https://greatsql.cn/docs/8.0.32-26/8-mgr/5-mgr-readwrite-split.html

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论