ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

MySQL主从架构下MaxScale读写分离与高可用实战指南

MySQL主从架构下MaxScale读写分离与高可用实战指南 搞数据库的兄弟应该都有过这种体验主从架构搭好了读写分离却迟迟没落到位。业务代码里手动判断哪个库写、哪个库读刚开始还行等Server挂了一台、主从切换过几轮之后各种连接串了、事务跑飞、延迟把从库拖垮的问题就全冒出来了。这玩意儿不是不能自己做而是做起来太费劲而且你做的永远没有专业中间件做得细。所以今天我打算完整写一写MySQL MaxScale Proxy这套方案从架构原理、安装配置、读写分离、高可用切换到平时根本不会写在官方文档里的坑一次性讲清楚。这篇指南适合谁一类是已经在用主从复制、想把读写分离和故障切换做得更正规的DBA和运维工程师另一类是后端开发同学你们不一定要亲手部署MaxScale但至少要明白中间件到底在哪一层做了什么不然碰上连接池报错事务被路由到从库这类问题会一头雾水。先说清楚MaxScale能帮你解决什么再一步一步把它配起来。1. MaxScale到底解决什么问题1.1 为什么需要数据库代理先说一个扎心的事实大多数业务系统读写比例至少在7比3很多互联网应用甚至是9比1。也就是说你的主库承担了大量根本不需要它承担的读压力。如果你有从库却没用起来那跟只有一个库没多大区别。那有人说了我直接在代码里配两个数据源不就行了应用层做读写分离确实是很多团队的第一版方案但你思考一下这几个场景主库挂了从库要顶上你的代码里的数据源地址要不要改改了之后应用要不要重启某个从库延迟特别大读它拿到的数据明显是旧的你的代码能感知到吗事务里先写了再读如果这条读被你自己的规则路由到从库你死都不知道怎么死的。这些问题的根源在于读写分离不只是发到不同库这么简单它需要感知后端每个节点的存活状态、复制延迟、事务状态。把这些逻辑塞进业务代码会让代码变得极其肮脏。数据库代理做的事情就是把这一层从业务里剥离出来由中间件统一管理后端的真实节点业务方只需要连接MaxScale这个入口就够了完全不需要关心背后有多少台数据库。1.2 MaxScale的核心功能和定位MaxScale是MariaDB官方出品的数据库中间件它跟MySQL的兼容性很好因为它本身就是为MySQL/MariaDB生态设计的。你可以把它理解成数据库前面的一个路由层应用连的是MaxScaleMaxScale再根据你配置的规则把SQL分发到后面的真实数据库节点。它最常用的几个能力读写分离自动把SELECT转到从库把INSERT/UPDATE/DELETE转到主库。负载均衡从库多的情况下可以让读请求分散到各个从库避免一台扛压。高可用切换配合Monitor模块监控后端节点状态主库故障时自动提升某个从库为新主库业务几乎无感知。SQL防火墙和审计能拦截危险SQL、限制特定用户的访问模式多一层安全保护。连接池减少频繁建连对数据库造成的开销。定位上它跟ProxySQL属于同类产品但两者侧重点不同。ProxySQL更偏重灵活的路由规则和查询缓存MaxScale更偏重跟MySQL主从复制生态的深度集成尤其是它的高可用切换能力是内置的不需要额外一堆脚本。如果你用的是MariaDB或者MySQL GTID复制MaxScale的Monitor模块做故障切换非常顺手。1.3 什么场景该用什么场景别用MaxScale不是银弹不是所有MySQL架构都得在前面架一层代理。我按实际经验给你分个类单机MySQL没有从库别用。多一层中间件就多一个故障点、多一份维护成本。主从架构读写比例明显分离强烈建议上。这是MaxScale最典型的应用场景。业务对数据库可用性要求极高希望主库故障时能快速切换用但要仔细配置Monitor和切换策略。现有应用代码完全没法改又想让数据库具备基本的路由分流能力直接考虑中间件方案别动代码。反过来如果你的团队对数据库中间件不熟悉又没人愿意花时间维护我建议你还是先在应用层用ORM的读写分离凑合或者等业务规模真到了必须分库分表的时候再连同中间件一起做标准化治理。2. 架构设计与部署规划2.1 读懂MaxScale的三大组件MaxScale的整体架构你可以拆成三块来看监听服务Listener。它对外开放端口接收应用的数据库连接请求。默认情况下MaxScale监听3306端口或者你自定义的路由端口应用只需要把数据库地址改为MaxScale所在机器的IP其他的连接方式不变。路由服务Service。这是核心逻辑层。你在配置里定义一个Service指定它用哪个路由模块例如readwritesplit再绑定多个后端服务器列表。Service决定了一条SQL进来之后应该发给哪个后端节点。监控模块Monitor。它负责盯着后端每一个MySQL实例的健康状态包括是否存活、复制是否正常、延迟多少、谁是主库谁是备库。监控模块不断把状态汇报给路由模块路由模块才敢放心分发请求。这三者加起来才是完整的代理能力。很多初次接触的人以为MaxScale只是个转发端口装上就能用其实必须把监控配好否则一切白搭。2.2 读写分离的底层判断逻辑MaxScale的readwritesplit模块判断一条SQL该去主库还是从库核心看三点第一SQL语句类型。SELECT默认去从库INSERT/UPDATE/DELETE/DDL去主库。这是最基本的判定。第二事务状态。关键点来了事务一旦开启或者事务里执行过写操作MaxScale会把该连接上的所有后续SQL都固定在主库直到事务提交或回滚。这样能保证事务内的读己之写一致性绝对不会出现先写后读却读到旧数据的尴尬。第三临时表、锁、系统函数等特殊情况。如果SQL里用了临时表、GET_LOCK()这类与连接状态强相关的操作MaxScale也会把连接固定到主库防止不同库之间状态不一致。另外readwritesplit还支持在SQL前面加hint注释来强制路由比如你想让某条查询强制走主库可以在SQL里加上MaxScale特定的hint。这个后面实操部分再说。2.3 高可用模式怎么选很多团队用MaxScale不只是为了读写分离还看重它的故障自动切换能力。MaxScale的高可用有两种模式自动故障转移failover。主库意外宕机时Monitor发现主库失联自动把数据最新的一台从库提升为新主库并让其余从库重新指向新主库。整个过程不需要人工干预适合无人值班的夜间故障。计划内切换switchover。你主动把一个从库提升为主库比如要做机房维护、主库硬件替换时用。切换前会保证数据一致性业务只会有秒级中断。要使用自动故障转移前提是后端MySQL必须开启GTID模式因为MaxScale需要基于GTID判断各从库的数据同步进度找出数据最新的节点。如果你还在用传统的binlogposition复制MaxScale也能监控主从状态但自动failover功能会受限建议直接上GTID。2.4 我建议的最小部署拓扑这里给出一套我实际验证过的最小高可用拓扑两个MySQL节点一主一从开启GTID半同步复制视业务情况开启。一台MaxScale节点不用很高配置2核4G即可因为它主要做转发不存数据。如果你需要VIP漂移再加一套Keepalived把VIP绑定在MaxScale节点上。这套拓扑能覆盖大多数读写分离高可用的需求。假设后期读压力大了加一台从库在MaxScale的服务器列表里多加一个节点就行应用无感知。假设MaxScale本身扛不住了可以再加一台MaxScale做双活配合Keepalived做VIP漂移实现入口高可用。3. 安装与基础配置实操3.1 安装MaxScale以CentOS 7/8或RockyLinux为例用MariaDB官方仓库安装最省事。先配置仓库再安装包# 配置MariaDB官方仓库以MaxScale 23.08版本为例 curl -LsS https://r.mariadb.com/downloads/mariadb_repo_setup | sudo bash -s -- --mariadb-server-version10.11 --maxscale-version23.08 # 安装MaxScale sudo yum install maxscale -y # 查看版本 maxscale --version如果是Ubuntu/Debian系统官方仓库方式类似用apt操作。装完之后MaxScale的二进制程序在/usr/bin/maxscale配置文件目录在/etc/maxscale.cnf老版本是单文件或者/etc/maxscale.cnf.d/新版本支持多文件。有一点提醒一下安装之前确认你的MySQL版本和MaxScale版本兼容。MaxScale官方有兼容性矩阵MySQL 5.7和8.0都在支持范围内但某些功能在8.0上需要额外配置比如使用caching_sha2_password认证时MaxScale需要相应的插件支持。我平时用mysql_native_password比较多测试环境没有踩到认证坑生产环境如果用8.0默认认证记得提前用MySQL Shell验证一下MaxScale能否正常连接。3.2 配置文件结构说明MaxScale的配置核心是/etc/maxscale.cnf新版支持include目录我建议你按模块拆分配置方便维护。整个配置文件的段落非常清晰[maxscale] 全局参数比如线程数、日志级别。[server1]、[server2] 定义后端数据库节点。[监听器] 定义端口和绑定的服务。[服务] 定义路由规则、负载策略和绑定的后端服务器。[监控器] 定义如何检测后端节点的健康状态。下面我直接给出一份可用的基础配置再一步步解释重点。3.3 创建MaxScale所需的数据库账号在配置MaxScale之前要先在MySQL主库上创建专用账号。一个给MaxScale用来监控节点状态一个给业务应用用来正常读写。注意业务账号不用在每台库上手动创建因为主从复制会把账号信息同步到从库你在主库建一次就行。-- 监控账号MaxScale Monitor模块使用 CREATE USER maxscale_monitor% IDENTIFIED BY MonitorPass2024; GRANT REPLICATION CLIENT, REPLICATION SLAVE, PROCESS, SELECT ON *.* TO maxscale_monitor%; -- 业务读写账号应用通过MaxScale连接时使用 CREATE USER app_rw% IDENTIFIED BY AppPass2024; GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO app_rw%; FLUSH PRIVILEGES;监控账号的权限要给到位特别是REPLICATION CLIENT必须至少具备这些权限才能读取主从状态信息如果权限不够Monitor模块会报insufficient privileges错误。另外我一般把监控账号的host设成MaxScale节点的IP而不是%安全第一。3.4 配置监听器和服务器列表先看核心节点配置。假设我的MySQL拓扑是192.168.1.10主库192.168.1.11从库MaxScale安装在192.168.1.20。# /etc/maxscale.cnf.d/servers.cnf [maxscale] threadsauto log_warning1 [server1] typeserver address192.168.1.10 port3306 protocolMariaDBBackend [server2] typeserver address192.168.1.11 port3306 protocolMariaDBBackend其中protocolMariaDBBackend是后端节点连接MySQL使用的协议不用改成MySQLBackendMariaDBBackend同时兼容MySQL和MariaDB。监听器这里也有讲究。业务连接监听器时认证方式默认使用MySQL的账号密码验证这意味着MaxScale本身不存账号它会把认证请求转发给后端真实MySQL节点验证。所以你在MaxScale配置里不需要创建业务账号只需要保证后端MySQL有对应账号就行。# /etc/maxscale.cnf.d/listener.cnf [读写分离-Listener] typelistener service读写分离-Service protocolMariaDBClient address0.0.0.0 port4006这里我把MaxScale的入口端口设为4006避免跟本机3306冲突。业务方连接数据库时host填192.168.1.20port填4006其他照旧。3.5 初始化启动和基本验证配置写完后先检查语法再启动# 检查配置 maxscale --config-check # 启动服务 sudo systemctl start maxscale sudo systemctl enable maxscale # 查看监听端口 ss -lntp | grep maxscale启动成功后用maxctrl命令查看后端节点是否被正确识别。maxctrl是MaxScale自带的命令行管理工具非常有用后面核心功能全靠它maxctrl list servers如果配置正确你会看到两个server的状态。刚开始两个节点应该都能正常识别但你可能发现它们都是Master或者都是Slave这类显示异常别急那是因为还没配置监控模块MaxScale现在根本不知道谁主谁从只知道能连上。4. 核心功能配置与实操4.1 配置Monitor监控模块监控模块是这套架构的眼睛。没有它MaxScale就是个盲人路由器谁主谁从全靠猜。所以这是我最看重的一步。# /etc/maxscale.cnf.d/monitor.cnf [MySQL-Monitor] typemonitor modulemaridbmon serversserver1,server2 usermaxscale_monitor passwordMonitorPass2024 monitor_interval2000 backend_connect_timeout3 backend_read_timeout3 detect_stale_master1 failcount3每个参数我解释一下这些在实际生产里都可能救你命monitor_interval2000每2秒检查一次后端节点状态。太频繁会增加数据库压力太慢会导致故障切换不及时2000毫秒是我用下来的合适值。failcount3连续3次检测失败才判定节点挂了防止网络瞬时抖动引发误切换。detect_stale_master1这个是自动failover的关键当主库失联后MaxScale会判断是否有数据足够新的从库可以顶上。还需要专门配置自动failover相关的参数。在MaxScale中自动failover不是默认开启的需要在monitor配置里显式声明。光能监控还不够要让它自动切换还得告诉它什么时候能切。我建议在monitor配置里加auto_failover1 auto_rejoin1auto_failover1主库故障时自动提升从库。auto_rejoin1原主库恢复后自动把它作为新主库的从库重新加入集群。这两个参数配合真正能做到故障后全自动恢复。但这里有个前提你必须记住所有MySQL节点必须开启GTID否则auto_rejoin很可能因为不知道同步位置而失败。配置好Monitor后重启MaxScale再用maxctrl list servers看一下sudo systemctl restart maxscale maxctrl list servers这时候你应该能看到server1显示Masterserver2显示Slave说明监控已经正确识别主从关系。4.2 配置读写分离服务接下来就是核心的读写分离Service配置。这也是业务流量真正开始走MaxScale的起点。# /etc/maxscale.cnf.d/service.cnf [读写分离-Service] typeservice routerreadwritesplit serversserver1,server2 usermaxscale_monitor passwordMonitorPass2024 master_accept_readstrue max_slave_connections255 max_slave_replication_lag5这里面几个关键参数值得重点说master_accept_readstrue允许读请求也发到主库。当一个从库挂了或者延迟严重时读请求会自动转向主库不至于报错。如果你是那种连主库都不希望被读请求碰的场景可以设成false但代价是可用性下降。max_slave_connections255最多允许多少个到从库的后端连接。默认值是一个连接数偏保守的值读并发大的场景建议调高否则从库资源利用不充分。max_slave_replication_lag5从库复制延迟超过5秒时MaxScale会暂时把该从库剔除出读候选列表防止读到太旧的数据。这个参数非常实用尤其是你在从库上跑了报表查询或者备份任务时延迟很容易飙升。配置完成后读写分离的路由规则就生效了。但你可能会问这行配置里routerreadwritesplit和servers都清楚唯一的疑问是为什么Service里也要配user/password这是为了让MaxScale能连到后端数据库获取一些元数据信息比如表结构、字符集等。这里可以直接复用监控账号也可以单独建一个只读账号看你管理习惯。4.3 配置负载均衡策略有多个从库时MaxScale默认采用轮询round-robin把读请求分发到各个从库。如果你希望根据从库的硬件配置分配不同权重可以在服务配置里这样写[读写分离-Service] routerreadwritesplit serversserver1,server2,server3 ... # server1是主库server2从库权重2server3从库权重1 server2weight2 server3weight1权重高的从库会被分配更多读连接。这个配置在混合硬件环境下很有用比如一台从库是SSD另一台从库是老旧SATA盘你总不能让SATA盘扛跟SSD一样多的流量吧。另外MaxScale还支持按连接数均衡和按响应时间均衡但这些需要额外配置策略模块。我自己的建议是中小规模先用轮询就够了等从库数量超过3台且配置差异明显时再考虑权重方案。4.4 配置SQL防火墙和用户管理读写分离配置好基本功能已经可用但一个生产环境入门的代理不能只做转发安全防护也要跟上。MaxScale自带SQL防火墙模块可以拦截一些危险操作。# /etc/maxscale.cnf.d/firewall.cnf [My-Firewall] typefilter moduleregexfilter matchdrop table|truncate table|delete from actionwarn这个示例是简单的正则过滤匹配到drop table、truncate table、delete from这类语句时记录日志并告警不真正拦截。如果你想要更严格可以把action改成block直接拒绝执行。但要注意actionblock是全局的别把正常业务的三方敏感词也误杀了正则匹配建议先在不影响业务的规则下跑一段时间观察日志再收紧。用户管理方面MaxScale的权限模型跟MySQL类似但它是从后端库加载用户信息。生产上我建议业务方分成只读账号和读写账号连接MaxScale时通过不同账号天然区分访问范围。这样就算有应用配置错误也只影响它自己的权限范围不会把整个库暴露。之前我见过一个团队所有应用都用root连MaxScale那中间件的安全过滤就完全形同虚设了。4.5 MaxCtrl命令实战maxctrl是MaxScale运维的生命线很多问题排查都靠它。我把最常用的命令列一下这些基本都是每天会用到的。# 查看所有已配置的后端服务器状态 maxctrl list servers # 查看当前服务状态读写分离服务接收的连接数 maxctrl list services # 查看监听器状态 maxctrl list listeners # 查看配置摘要 maxctrl show servers # 手动将主库切换到指定从库 maxctrl call command mariadbmon switchover MySQL-Monitor server2 # 查看MaxScale日志 sudo journalctl -u maxscale -f你重点关注list servers输出里每个server的state列。读操作应该分发到Slave状态的节点写操作分发到Master状态的节点。如果你看到某个节点长时间是Down或者Maintenance状态优先去检查该节点MySQL服务是否正常、MaxScale到它之间的网络是否通、监控账号权限是否够。另外有个实用技巧在进行计划内维护时先用maxctrl把节点状态置为Maintenance它就不会接收新请求了你可以在它上面安心做操作而不影响线上流量。操作完再切回正常状态。这个功能我每次做MySQL升级都靠它非常稳。5. 高可用切换实操5.1 主从切换的原理与前置条件很多人最大的顾虑是MaxScale自动切换到底靠不靠谱说实话任何自动切换都不是绝对安全的你要理解它的原理才能把握风险的边界。MaxScale主库故障时的动作大致如下Monitor检测到主库连续失败达到阈值之后会先判断是否存在数据可以补上来的从库。它依据的是各从库GTID集合与主库的差距选出数据最新的从库尝试让其余从库先追上这个从库的GTID位置然后选举它为新主库剩余从库自动repoint到新主库。整个过程从检测到切换完成通常在几秒到十几秒之间取决于从库数量和数据量。前置条件我强调三遍GTID必须开启GTID必须开启GTID必须开启。没有GTIDMaxScale的自动选主逻辑就跟蒙着眼睛摸牌一样完全不可靠。主库和从库开启GTID的方式网上很多这里不展开但要确保gtid_modeONenforce_gtid_consistencyON。还有个前提MaxScale本身不能成为单点。如果只有一台MaxScale它挂了整个数据库入口照样瘫痪。生产环境建议两台MaxScale Keepalived VIP一台挂了VIP漂移到另一台这样才达到真正的高可用。5.2 模拟主库故障看自动切换效果纸上谈兵不如实战演练。我通常会在测试环境亲手把主库MySQL停掉观察MaxScale的行为。# 在server1主库上模拟宕机 sudo systemctl stop mysql # 在MaxScale节点观察节点状态变化 watch -n 1 maxctrl list servers正常情况下几秒之后你会看到server1状态变成Down再过几秒server2状态从Slave变成Master。这个过程不需要人为干预。然后你再用业务账号连接MaxScale试一下写操作INSERT INTO appdb.test_table (id, name) VALUES (1, hello); SELECT * FROM appdb.test_table;写操作会成功走到新主库读操作会自动分发到新的主库或从库。对于应用来说它从头到尾只是连着一个MaxScale入口根本不知道背后数据库主从已经换了一轮。这就是中间件的价值。有一个需要注意的细节切换瞬间在途的事务会回滚应用侧会看到连接中断的错误。所以业务代码一定要做好重连机制。大多数连接池会自动建新连接你只要确保应用的数据库连接池支持重连就行比如Druid、HikariCP都有相关配置项。5.3 原主库恢复后的处理主库故障后如果它只是机器重启而不是彻底报废恢复后MaxScale配合auto_rejoin1应该会自动把它作为新主库的从库加回来。你可以通过maxctrl list servers看到它变成Slave状态。但如果auto_rejoin没有生效或者你为了保险想手动操作过程也不复杂# 在恢复的原主库上把它指向新的主库 CHANGE MASTER TO MASTER_HOST192.168.1.11, MASTER_USERrepl_user, MASTER_PASSWORDxxx, MASTER_AUTO_POSITION1; START SLAVE;然后确认show slave status里Seconds_Behind_Master变为0。等它跟上了再放回MaxScale的服务列表里接受读流量。这里我吃过一个亏原主库恢复后由于binlog里可能已经包含了它之前当主库时的数据直接作为从库接进来轻则报错重则数据不一致。所以恢复时最稳妥的做法是先把原主库的binlog和relay log清掉让它以全新的身份重新加入集群。具体操作就是在CHANGE MASTER之前先RESET MASTER清理binlog。但注意这只适合已确认原主库数据可以从新主库完整拉取的场景如果原主库上还有新主库未曾拥有的数据你得先把数据补过去否则切回来会丢数据。5.4 计划内切换的正确姿势如果不是故障而是计划内维护比如主库要升级硬件、调整参数建议用switchover而不是直接停库。switchover的好处是它会在切换前做数据一致性检查尽量保证切换不丢数据。# 假设当前server1是主库想平滑切换到server2 maxctrl call command mariadbmon switchover MySQL-Monitor server2执行后MaxScale会先让server2追平主库数据然后通知应用断开连接把server2提升为主库最后把server1变成从库。整个过程业务中断时间很短通常1秒左右配合连接池重连机制应用几乎无感。计划内切换前我强烈建议你先做一次后端全量备份并且挑业务低峰期执行。别问我为什么有一次我在白天高峰期做switchover结果某个报表任务刚好在跑大查询切换时连接重置任务失败业务方盯了我一下午。从那以后所有切换操作我都至少提前一晚通知业务方并且安排在凌晨。5.5 与Keepalived结合解决入口高可用MaxScale本身处理了数据库层的故障但MaxScale这台服务器挂了怎么办答案是用Keepalived做VIP漂移让两台MaxScale共享一个虚拟IP。拓扑是这样的两台MaxScale节点192.168.1.20和192.168.1.21都安装Keepalived配置相同的VIP比如192.168.1.100。正常情况下VIP绑定在节点A上应用连接192.168.1.100:4006如果节点A宕机Keepalived自动把VIP漂移到节点B。业务连接池里的旧连接虽然会断开但连接池会自动重新连到VIP此时流量已经由节点B接管。Keepalived的配置网上很多核心就是设置virtual_ipaddress和VRRP实例这里不再贴长配置。要提醒的是Keepalived只能保证VIP漂移不能保证后端状态一致性。节点B接管后它的MaxScale配置必须跟节点A保持一致才能正确接管流量。所以两台MaxScale的配置文件最好用配置管理工具统一分发避免手动改动导致两边配置漂移。6. 常见问题与排查技巧实录6.1 应用连接报错连不上MaxScale最常见的问题是应用配置了MaxScale地址和端口但连接时提示access denied或者connect timed out。排查顺序如下先确认MaxScale监听端口是否正常ss -lntp | grep 4006如果监听都没起来看日志journalctl -u maxscale -f。再确认业务账号在后端MySQL存在且允许相应来源IP连接。注意MaxScale连接后端时认证是通过后端MySQL完成的你需要确保业务账号的host范围包含应用服务器IP或应用通过MaxScale访问时的来源IP。如果错误是Unknown database检查业务连接的数据库名是否存在MaxScale不会帮你建库。如果错误是Too many connections那是后端MySQL连接数满了检查max_connections和MaxScale连接池配置。6.2 事务被路由到从库读到旧数据这个问题出现频率极高而且排查起来不直观。现象是应用在一个事务里先insert再select结果select读到的是旧数据。很多人第一反应是MaxScale路由bug其实多半是应用连接方式的问题。MaxScale的readwritesplit识别事务依赖看它是否收到BEGIN/COMMIT语句。如果应用使用了框架的事务控制但某些情况下事务不是通过显式BEGIN开启的比如在autocommit0模式下直接执行SQLMaxScale可能不会把该连接识别为事务中于是后续SELECT就会去从库。解决办法是在连接串或者框架配置里强制使用显式事务确保每个事务都有BEGIN和COMMIT/ROLLBACK。另外Java的JDBC如果开启了useLocalTransactionStatetrue某些驱动优化会避免发送BEGIN语句也会导致这个问题。所以遇到这种问题先排查事务是不是被真正发到了服务器而不只是框架层面的逻辑事务。6.3 从库延迟导致业务读到脏数据从库延迟是读写分离永远绕不开的话题。业务方时常抱怨明明刚更新成功查询却看不到新数据。这个不一定是MaxScale的问题而是数据还没复制到从库。我建议从两个层面解决一是用max_slave_replication_lag参数设置延迟阈值超过阈值的从库自动移出读候选这个前面已经讲过。二是关键业务强制走主库可以在SQL前加MaxScale hintSELECT * FROM appdb.orders WHERE id 100; -- 强制走主库的hint写法 SELECT /* master */ * FROM appdb.orders WHERE id 100;但这种hint只能用在单一SQL上如果整个逻辑都必须读主库我更推荐在应用里单独配置一个主库专用数据源绕过读写分离。毕竟中间件解决大部分问题小部分敏感场景要留手动开关。6.4 MaxScale性能瓶颈和参数调优MaxScale本身很轻量但如果配置不当也可能成为瓶颈。最常见的坑是threads参数。默认threadsauto会根据CPU核数自动配置这通常没问题。但如果你在容器环境里运行可能会因为容器可用的CPU核数限制导致线程数配置不理想。我建议显式设置threads为容器分配的CPU核数。另外我遇到过MaxScale连接数被打满导致应用排队的情况。监听的max_connections是后端MySQL的连接数上限而MaxScale的max_connections是它到后端服务的连接数默认值通常是10000一般情况下够用。真正需要关注的是后端MySQL的max_connections因为多个应用都通过MaxScale连接时后端的连接复用率直接取决于MaxScale连接池的配置。如果每个请求都新建连接那风险转移到了数据库侧。日志也是一个值得关注的调优点。MaxScale默认日志级别是warning但如果排查问题需要更细的信息可以临时把log_warning调高到debug排完再降回来。别长期开着debug日志增长很恐怖磁盘会先扛不住。6.5 升级备份与日常维护MaxScale升级要谨慎我一般遵循先备后升、先测试后生产的原则。升级前至少做好两件事第一备份配置文件。MaxScale的所有核心配置都在/etc/maxscale.cnf和.cnf.d目录下整个目录备份下来恢复时直接放回去就能用。第二确认后端MySQL和MaxScale版本兼容。MaxScale版本迭代很快大版本升级前务必查一下官方兼容性矩阵尤其关注认证插件变化和路由模块行为变化。我自己吃过一次亏从6.x升到23.08时某些旧配置项被废除了服务直接起不来最后挨个对照官方变更日志改配置才恢复。日常维护方面我每周会定时跑一次maxctrl list servers确认节点状态每月做一次主从切换演练。别觉得麻烦真等到故障发生才第一次演练那时候你大概率手忙脚乱。另外监控报警一定要做。MaxScale进程本身挂了、后端节点状态异常、复制延迟过高都应该通过你的监控平台及时告警。我见过不止一个公司MaxScale挂了几个小时无人知晓因为所有注意力都在MySQL上忽略了中间件本身也是一个需要被监控的重要组件。写在最后的个人体会MaxScale这套东西初看是个配置项很多的路由器实际用久了你会发现它的价值关键不在某一条配置而在于把复杂运维逻辑从业务里抽离出来这件事上。业务团队不再需要关心当前谁是主库不需要自己处理故障切换后的连接变更这省下的人力成本远超中间件本身的部署成本。我的建议是如果你正在管理一套主从架构别急着让应用层自己写路由先花一个下午按这篇指南把MaxScale跑起来再花半天做一次故障演练。等你在测试环境亲眼看到主库被杀掉、业务依然正常读写的时候你就知道这套方案值不值得上了。
返回列表