
我折腾MySQL中间件这几年有一个很深的体会大部分团队一开始根本不需要引入复杂的分布式数据库一台主库配上几台只读从库再架一层轻量级的访问代理就能扛住绝大多数读写压力。这个代理层在国内最经典、也最容易被低估的方案就是360开源的Atlas。Atlas是基于MySQL官方Proxy 2.0.1版本改造而来的本质上是一个位于应用和MySQL实例之间的透明访问中间件。它的核心价值就是帮你把“读写分离”和“分库分表”这两件以前需要改业务代码才能做的事下沉到数据访问层统一处理。这篇文章不聊虚的我就从实际部署、核心参数、踩坑经历三个角度把这个组件讲透。不管你是刚接触数据库中间件的新手还是正在做技术选型的后端开发这篇都能给你一些能直接落地的参考。1. 内容整体设计与思路拆解1.1 为什么你的架构需要中间件这一层先想一个问题当你的业务量涨起来数据库的读压力远大于写压力时最通用的扩容手段是什么绝大多数人第一时间想到的是加从库做读写分离。但问题来了业务代码里如果到处写死了数据库连接地址你怎么让写请求只发往主库、读请求均衡分发到各个从库改代码让每个服务自己维护数据源路由规则这事儿听着就能做但实际上又繁琐又容易出错。真正合理的思路是在应用和数据库之间隔一层透明代理。应用连接代理代理负责把SQL请求分类——是SELECT就分发到从库是INSERT/UPDATE/DELETE就固定发给主库。这样业务代码完全不用感知底层数据库拓扑的变化加从库、切换主库对上层都不可见。这层代理的角色就是Atlas这类中间件在设计上的核心出发点。1.2 Atlas在技术版图里的定位现在市面上数据库中间件不少MyCAT、ShardingSphere、Vitess各有各的侧重。但Atlas有一个鲜明的特点它走的是传统代理路线部署形态简单就是一个独立进程前端用MySQL协议跟应用交互后端用标准MySQL协议连接真正的数据库实例。这种形态带来一个天然优势——它对应用语言的侵入性为零不管你是Java、PHP、Go还是Python只要程序能连MySQL就能连Atlas。我当初选它还有一个现实考量团队当时没有精力去改造ORM层引入那种需要嵌入到业务代码里的中间件意味着每个服务都要改配置、改依赖工作量太大。Atlas这种纯代理模式上线周期可以压缩到半天以内特别适合想快速缓解数据库压力、又不想大动干戈的中小型团队。1.3 选型之前必须认清的两个边界任何技术都有适用边界Atlas也不例外。第一它不像NewSQL那样具备分布式事务能力跨库事务需要业务层自己控制这也是所有分库分表中间件的共同限制。第二它本身不解决数据同步问题主从复制仍然依赖MySQL原生的binlog机制。如果你从库延迟过高读写分离的读一致性就会受影响。搞清楚这两点你对Atlas能做什么、不能做什么心里就有底了。2. 核心功能与方案选型解析2.1 读写分离Atlas的核心看家本领读写分离是Atlas最成熟、用得最广的功能。它的实现原理在上面已经提过但实际落地时有不少细节值得展开。Atlas在处理SQL时会做一层轻量的词法解析判断语句类型。SELECT、SHOW、DESC这类读操作会按照你配置的负载均衡策略分发给后端的某个从库其他写操作及事务语句则固定走主库。但这里有个关键点如果你在一个事务里先执行了UPDATE再执行SELECT这条SELECT能不能被路由到从库答案是不能。Atlas为了保证事务内的一致性一旦某个连接进入了事务状态它后续的所有语句都会发往同一个后端数据库直到事务提交或回滚。这个设计非常务实——它避免了在主从延迟下事务里刚写入的数据读不到的问题。2.2 分库分表何时能用怎么配置Atlas对分库分表的支持走的是“库表映射”的路子。你需要提前规划好分片规则比如把用户ID按哈希分到4个库里配置里把逻辑表映射到物理表。它不像有些中间件那样支持灵活的分布式Join和聚合运算所以它对SQL本身有要求——单表操作最理想简单Join还可以复杂Join和子查询尽量别用。坦白说现在新项目做分库分表我更推荐先考虑ShardingSphere这类功能更全面的方案。但如果你手里有一套老系统表结构已经基本固化只是单库容量到了瓶颈想赶紧把数据拆到多个实例上去Atlas的分库分表能力仍能派上用场。它的配置形态简单直接映射关系一目了然运维上手成本很低。2.3 负载均衡与健康检查保障高可用的底座Atlas后端的每个MySQL实例都有权重配置你可以根据机器性能分配流量比例。比如主库CPU是8核从库是4核那权重就可以设成2比1。同时Atlas会周期性地对后端实例做健康检查发现某台从库宕机会自动把它从可用列表里摘除应用感知不到任何变化。这里有个配置技巧健康检查不只是检测端口通不通你还可以指定一条检查SQL比如SELECT 1确保实例在MySQL层面是真正可用的。端口能连上但数据库内部有问题的情况在生产环境里发生过不止一次。3. 实操过程与核心环节实现3.1 环境准备与安装编译Atlas的官方发行版默认是用glibc编译的如果你用的系统是CentOS 6或7可以下载预编译的二进制包解压即用。如果你跟我一样用的是比较新的操作系统版本比如CentOS 8、Ubuntu 20.04直接跑二进制可能会报错这时就需要从源码编译。我踩过的坑是新系统缺少libffi-devel等依赖编译时反复报头文件缺失。提前用yum装好依赖包能省不少时间。# CentOS下安装基础依赖 yum install -y gcc gcc-c glibc-devel libffi-devel libevent-devel glib2-devel mysql-devel # 解压源码包 tar -zxvf Atlas-2.2.1.tar.gz cd Atlas-2.2.1 # 编译安装 ./autogen.sh ./configure --with-mysql-lib/usr/lib64/mysql make make install编译完成后默认安装目录是/usr/local/mysql-proxybin目录下放着mysql-proxy主程序conf目录是配置文件lib目录下是Atlas自己实现的读写分离和分库分表逻辑。3.2 最小化配置文件实战Atlas的配置文件是兼容MySQL风格的ini格式核心配置项并不多。我给你们看一份我实际部署时用过的精简配置三个后端实例对应一主两从[mysql-proxy] # 管理接口的用户名密码 admin-username admin admin-password admin123 # 代理服务监听地址与端口应用连这个地址 proxy-address 0.0.0.0:1234 # 管理接口监听地址与端口DBA用这个做管理 admin-address 0.0.0.0:2345 # 后端主库write proxy-backend-addresses 192.168.1.101:3306 # 后端从库read多个用逗号分隔 proxy-read-only-backend-addresses 192.168.1.102:3306,192.168.1.103:33062 # 分库分表的规则文件 # proxy-config /usr/local/mysql-proxy/conf/table_sharding_rule.conf # 对应用户格式为 用户名:密码IP段 pwds dba_user:xxxxx192.168.1.0/24注意看一下从库那行的写法。默认每个从库的权重是1如果你希望第二台从库承担更多读流量就在IP后面加符号和权重值。上面配置里192.168.1.1032代表它的权重是2接收的读请求数量会是旁边那台从库的两倍。3.3 启动服务与基础验证配置写完后启动方式非常简单/usr/local/mysql-proxy/bin/mysql-proxy --defaults-file/usr/local/mysql-proxy/conf/proxy.conf生产环境建议用nohup或systemd做守护避免进程意外退出。启动后先确认两个端口在监听netstat -tlnp | grep -E 1234|2345如果端口起来了用应用账号试连一下代理端口执行几条SQL看看路由效果mysql -h127.0.0.1 -P1234 -udba_user -p # 查看当前连接的后端地址在Atlas里可以执行这条命令 mysql /*proxy*/show proxy backend;这个/proxy/前缀是Atlas的管理指令执行后能看到每条连接的当前后端是主库还是某个从库。我第一次看到这个输出时读写分离的路由逻辑一下就清晰了。3.4 管理接口的使用技巧Atlas的管理接口容易被人忽略但在排障时简直救命。用MySQL客户端连上2345端口就能执行一些在线管理命令比如查看连接状态、动态调整后端实例等。-- 查看后端实例状态 SELECT * FROM backends; -- 手动摘除某台从库 SET BACKEND DOWN 2; -- 重新启用某台从库 SET BACKEND UP 2;这里的操作不需要重启Atlas对线上连接没有任何影响。我之前在给从库做系统升级前就是先手动把对应后端置为DOWN等升级完再置为UP全程业务无感知。4. 配置参数深度解读与调优4.1 连接池与线程模型参数Atlas本质上是一个多线程代理它需要同时维护大量前端连接和后端连接。以下这几个参数对性能和稳定性影响最大逐个说明参数名说明生产建议值event-threads处理网络事件的工作线程数CPU核数的2~4倍max-connections前端最大连接数视业务规模而定一般为2000~5000wait-timeout空闲连接超时时间秒288008小时与MySQL保持一致keepalive是否开启TCP保活1开启event-threads设置过大或过小都会有问题。太少了高并发下事件处理不过来延迟会飙升太多了线程上下文切换的开销反而拉低吞吐。我一般习惯先按CPU核数的2倍设置压测后根据CPU使用率和延迟曲线微调。4.2 客户端IP访问控制Atlas的pwd参数里可以设置IP段白名单。这个能力在混合云架构下特别好用——你可以精确控制哪些网段能访问代理端口避免数据库端口直接暴露在内网甚至公网。配置里我建议不要把0.0.0.0/0写进白名单安全上的收益非常有限风险却大得多。4.3 SQL日志与慢查询定位排查问题时SQL日志是重中之重。Atlas提供了sql-log和slow-sql-log两个开关配合日志级别控制可以在不影响性能的前提下把慢SQL和错误SQL记录下来。# 开启SQL日志 sql-log ON # 开启慢SQL日志慢于1秒的执行会被记录 slow-sql-log ON slow-sql-time 1000 # 日志存放路径 log-path /usr/local/mysql-proxy/log这里有个经验之谈sql-log在生产环境长期全开日志量会非常大磁盘增长很快。我通常的做法是平时只开slow-sql-log出故障时再临时打开全量SQL日志定位完关闭。相信我这能替你省下不少磁盘空间和排查日志时折磨人的时间。5. 常见问题与排查技巧实录5.1 主从延迟导致的数据读不到这是读写分离架构绕不开的经典问题。有一次上线活动用户反馈刚下的订单在订单列表里看不到。查了后端数据库数据主库里有从库里还没同步过来。Atlas把这条查询路由到了延迟的从库导致出现“数据丢了”的假象。排查思路先看从库的Seconds_Behind_Master指标再结合Atlas的连接路由情况判断。解决手段有多条路在从库追上主库前临时把这个从库从Atlas中摘除。对于强一致的读场景在业务层把这类查询标记为走主库可以在SQL里加hint的方式。优化复制链路比如升级实例规格、开启并行复制。5.2 连接数被打满的诡异故障有次线上告警Atlas的连接数一路涨到上限新连接全部被拒。检查后端MySQL连接数倒是没满。最后发现是我们的应用侧连接池配置了过大的maxPoolSize而且连接池没有做有效的空闲回收导致大量连接挂在Atlas上不释放。这个问题的根源不在Atlas而在应用侧的连接池配置。解决方案是应用侧合理设置maximumPoolSize一般建议单实例不超过50同时开启连接泄漏检测防止连接被业务代码异常占用后不归还。5.3 编译安装时的依赖地狱我开头提过源码编译Atlas在新版Linux系统上会遇到不少依赖问题。这里补充一个更具体的坑有些系统没有安装mysql-devel包configure阶段会提示找不到mysql_config导致直接退出。还有libevent-devel和glib2-devel缺失编译时会在链接阶段报各种奇奇怪怪的错误。解决方法是编译前用下面的命令把依赖全部补齐yum install -y libevent-devel glib2-devel mysql-devel libffi-devel如果你用的是Ubuntu/Debian系列对应的是libevent-dev、libglib2.0-dev、libmysqlclient-dev、libffi-dev包名略有差异但逻辑一样。5.4 分库分表规则不生效的排查规则文件配置了但流量没有按预期分发到不同的库。这种问题八成是规则文件里的schema名或表名跟实际SQL对不上。Atlas在做库表映射时是严格匹配的大小写、反引号都会影响匹配结果。还有一种情况是配置了proxy-config参数但规则文件路径配错了Atlas启动时静默跳过直连了后端单库。遇到这种情况启动时加上--log-leveldebug日志里会明确打印规则加载结果。6. 运维经验与监控体系建议6.1 进程守护与自动拉起Atlas作为代理层它的可用性直接决定了业务的可用性。生产环境必须配置进程守护我建议使用systemd而不是简单的crontab脚本因为systemd可以精确控制启动顺序和失败重启策略。[Unit] DescriptionMySQL Atlas Proxy Afternetwork.target [Service] Typeforking ExecStart/usr/local/mysql-proxy/bin/mysql-proxy --defaults-file/usr/local/mysql-proxy/conf/proxy.conf ExecReload/bin/kill -HUP $MAINPID Restartalways RestartSec3 [Install] WantedBymulti-user.target6.2 监控指标体系Atlas自身不带监控面板但它的状态信息可以通过管理接口抓取。我建议至少监控这几个维度进程是否存活、端口是否在监听。后端实例的状态是否频繁出现DOWN/UP抖动。并发连接数趋势接近上限时要提前扩容或优化。慢SQL频率变化突然增多通常意味着后端MySQL出了问题。QPS/TPS的整体趋势用于容量规划。可以用自研脚本或接入Prometheus这类监控系统定时抓取管理接口数据入库配置告警规则。我第一次把Atlas接入监控体系后很多潜在问题都能在用户反馈之前暴露出来。6.3 版本升级与兼容性验证Atlas本身的迭代早已停止不建议在它上面追求新功能。如果遇到安全更新或操作系统兼容问题优先考虑架构升级到更现代化的中间件而不是在旧版本上打补丁。如果坚持用至少保证操作系统版本和glibc版本与Atlas编译环境匹配否则上了生产环境后出现诡异的内存问题排查会非常痛苦。7. 写在最后的经验沉淀折腾Atlas三年多我对数据库中间件这件事有了更深的理解。中间件永远是一个权衡的产物——它简化了业务侧的数据访问复杂度但把复杂度转移到了运维侧。引入它之前一定要想清楚自己的团队有没有能力承接这个运维成本。Atlas本身不复杂真正的复杂度在后端MySQL的高可用架构、主从复制的一致性保障以及业务侧对数据一致性模型的理解上。如果你问我什么时候适合上Atlas我会说业务读多写少、MySQL主从复制已经稳定跑了一段时间、不想大改业务代码那么Atlas值得一试。它在简单场景下的表现足够让团队用最小的代价撑过业务增长最快的阶段。