☰
Atlas数据库中间件实战:MySQL读写分离部署与配置详解
2026/10/19 8:49:50 网站建设 项目流程

到底什么是atlas?如果不限定领域,这名字能扯出好几份完全不同的事业线:地图册、数据库中间件、机械臂末端执行器、放疗计划系统、一个开源的表情包数据集……技术圈里最常碰到、也最值得掰开揉碎聊聊的,是数据库中间件这颗“旧糖”。我最早接触atlas是做MySQL读写分离改造的时候,业务量涨到主库连接数撑不住,又不想在应用里硬编码多数据源,折腾了一圈最终落在atlas上。这篇文章不是官方文档的复读,而是我把atlas从部署、配置、调优到踩坑这整套流程走完后的实操总结,适合刚接手数据库中间件、或者正在为读多写少业务做架构选型的朋友参考。

1. atlas整体设计与核心思路

1.1 它真正解决的问题是什么

先说清楚atlas到底干了什么。它本质上是一个位于应用和MySQL之间的代理层,工作在MySQL协议层,对客户端呈现为一个MySQL实例,对后端则负责把SQL按规则转发到不同的真实MySQL节点。最常见的用法是读写分离:主库处理写请求,从库处理读请求,这样一个逻辑入口就把后端的多节点拓扑藏起来了。

我遇到过不少团队的初始方案是在业务代码里写两个数据源,读走A连接写走B连接,本地调试没问题,一上灰度就出乱子:事务B踩到只读从库、延迟导致读不到刚写入的数据、某张报表SQL把从库打爆。这些问题的根源是业务和数据库拓扑耦合了。atlas的价值在于把“请求该去哪个库”这个决策从业务代码中剥离出来,由中间层统一处理,客户端只需要连接atlas的地址,像连普通MySQL一样发SQL就行。

1.2 为什么是atlas而非其他方案

市面上类似角色还有不少:MySQL官方Route、MaxScale、ProxySQL、ShardingSphere等等。我当时选atlas,核心原因是三个字:轻、透、稳。

轻是指部署简单,单个二进制加一个配置文件就能起来,不像ShardingSphere那样要么引入Java依赖做应用内代理,要么搭一套独立的Java服务,对中小团队来说维护成本偏高。透是指它专注在协议转发层,不搞乱七八糟的额外功能,连接池、读写分离、简单分表,场景覆盖得刚刚好。稳则是因为它源自奇虎360,经历过大流量线上环境的考验,有很多像连接数管理、后台管理接口之类的细节考虑得比较周全。

当然它也有先天不足,比如对复杂分片支持有限、配置文件改动要重启进程才生效、后面维护节奏放慢等,所以选型时别指望一个atlas包打天下,它就是一把用得顺手的螺丝刀,不要拿它当瑞士军刀使。

1.3 一次SQL请求的完整旅行

用一个具体例子说明atlas的工作流程。客户端发起SELECT * FROM user WHERE id=100:

  1. 客户端建连到atlas监听端口,atlas按配置的proxy-backend-addresses和proxy-read-only-backend-addresses分配后端的连接。
  2. SQL语句进入atlas的SQL解析模块,判定类型。
  3. 如果是SELECT、SHOW等读语句,在没有开启事务的上下文时,atlas会把请求哈希到只读后端中的某一个节点执行;如果是INSERT、UPDATE、DELETE、DDL等写语句,则路由到主库。
  4. 如果客户端显式执行了BEGIN/START TRANSACTION,在事务提交或回滚之前,所有SQL一律走主库,保证事务的隔离性和一致性。

这个过程在客户端侧是无感的。你拿mysql -hatlas_ip -P1234去连,执行SHOW VARIABLES之类还能正常返回,但实际数据是从代理绕了一圈才拿到。

2. 关键配置项与路由规则深度解析

2.1 配置文件体系概述

atlas的配置不像一些新项目用YAML或者键值对一套到底,它分了两块:主配置文件和分表规则文件。主配置文件在conf/目录下,通常是以实例名命名的test.cnf。配置语法是Linux常见的key = value格式。初次看到会觉得有点像MySQL的my.cnf,但每一项的含义差很多。

分表规则文件也叫tables文件,路径由主配置里的tables项指定。主配置文件控制实例的基本行为,分表规则文件描述哪些表做了分片、分片键是什么、分片算法怎么算。

2.2 主配置里最重要的几个参数

直接挑生产环境必须理解到位的几个参数说。

  • proxy-address = 0.0.0.0:1234:atlas对外暴露的MySQL协议地址,客户端连接这个端口。为了兼容习惯,这个端口建议尽量用3306或者接近3306的端口,有些老的ORM框架会对端口做特殊处理。
  • proxy-backend-addresses = 192.168.1.10:3306:写后端,也就是主库地址。可以配多个,但这个中间件对多主场景不建议依赖它,写路径还是单主更可靠。
  • proxy-read-only-backend-addresses = 192.168.1.11:3306,192.168.1.12:3306:只读后端,也就是从库实例。多个从库地址用逗号分隔,写库要执行轮询算法进行负载分发。
  • pwds = root:加密密文:客户端认证的账号和密码,密码不是明文,需要用atlas自带的加密工具对明文密码进行编码,然后把密文写到配置里。
  • admin-address = 0.0.0.0:2345:管理接口地址,后续想查看后端状态、在线踢连接都靠这个接口。

2.3 读写分离的路由逻辑细化

把路由逻辑再往前推一步。atlas对于SELECT的处理不是无脑走从库,有几个细节需要注意:

  • 如果SQL语句带FOR UPDATE锁,这类语句虽然语法上是SELECT,但本质是写操作,atlas对SELECT ... FOR UPDATE会识别出来并路由到主库。
  • 带LOCK IN SHARE MODE的查询也是类似逻辑。
  • 存储函数、存储过程中的读写操作,atlas只能在调用层面判断,函数内部的语句不会被分析和路由,所以涉及存储过程尽量在配置层面把这类调用整体路由到主库,或者避免用存储过程。
  • 对于不在事务里的SELECT,atlas会在多个从库之间轮询分发,第一次连A,第二次连B,依次循环。

这个路由结果是希望在绝大多数场景下,读压力能均匀分摊到各从库,而不是一台被打到高负载。

2.4 分表规则与分片键选择

如果你有单表数据量过大、想按某种维度拆开存储的需求,atlas也提供了基于分片键的分表能力。配置文件写法类似:

tables = user.id.hash, order.id.range

这个写法里,每一段表示一张表的分表方式。以user.id.hash为例,含义是对user表按id字段做哈希分片;order.id.range表示按id做范围分片。分片数量在分表规则文件中定义,比如user切成4张表,哈希值的计算会对分片数取模,落到对应分片。

分片键的选择是分表的核心,如果选错了,整个分表的收益就是负数。实际经验是:

  • 分片键必须出现在绝大多数查询的WHERE条件里,否则中间件只能把查询广播到所有分片,然后在内存里汇总,这个开销巨大。
  • 分片键的基数要够大,比如用户ID、订单ID、手机号都算可以,别选性别、状态这种只有几个取值的字段。
  • 如果业务有按时间维度滚动查询,range分片会更友好,能把冷热数据分离;如果是随机点查居多,用hash分片更均匀。

2.5 atlas的密码加密机制

配置里所有业务账号的密码都必须用atlas自带的加密工具生成。这一步很多人会忽略,直接写明文的pwds = root:123456,然后启动报错或者客户端认证失败。

正确做法是在安装目录的bin下面能找到encrypt工具,执行:

./bin/encrypt 123456

终端会输出一串密文,把这串密文粘贴到配置文件的pwds字段里。注意pwds字段的格式是用户名:密文,多个用户用逗号分隔。在测试调试阶段也可以用--help看下选项,不要直接在进程启动命令行里跨过配置写明文密码,否则有泄露风险。

3. 实操部署:从安装到第一笔读写分离

3.1 环境准备与依赖规划

部署atlas之前,先亮出我推荐的软硬件基线,供你参考:

  • 操作系统:CentOS 7.x或Debian系都可以,glibc版本不要太老。
  • 依赖库:libevent、glib、mysql client库等,安装时如果有缺失会有明确提示,装好即可。
  • 部署目录:建议单独放在/opt/atlas或者/data/atlas,不要放在系统临时目录,因为日志和配置要长期留存。
  • 建议以独立系统用户运行,比如新建一个atlas用户,避免直接用root跑代理进程。

3.2 安装步骤详解

atlas的安装方式比较简单,官方提供的是编译好的二进制包,解压即用。

tar -zxvf atlas-2.2.1.el6.x86_64.tar.gz mv atlas-2.2.1.el6.x86_64 /opt/atlas cd /opt/atlas

解压后的目录结构通常包含bin、conf、log等子目录。首次启动前需要确认二进制有执行权限,配置文件是否就位。

之后进入配置阶段,这是整个部署里最容易出错的一步,我用一个实际例子说明完整配置。

[mysql-proxy] # 对外服务地址 proxy-address = 0.0.0.0:1234 # 管理接口地址 admin-address = 0.0.0.0:2345 # 管理员账号 admin-username = admin admin-password = admin # 主库地址,多个用逗号分隔 proxy-backend-addresses = 192.168.1.10:3306 # 从库地址 proxy-read-only-backend-addresses = 192.168.1.11:3306,192.168.1.12:3306 # 业务账号 pwds = root:OZkGX1fLfQ8= # 分表规则文件 tables = conf/tables # 日志级别 log-level = message # 日志路径 log-path = log/

配置完成后,可以用以下命令把atlas启动起来:

/opt/atlas/bin/mysql-proxy -d --defaults-file=/opt/atlas/conf/test.cnf

-d表示以守护进程方式运行。启动后立刻看看进程是否存活:

ps -ef | grep mysql-proxy

再到日志目录看有没有报错。如果进程起来了,但客户端连不上,优先查看监听端口:

netstat -tlnp | grep 1234

3.3 验证读写分离是否生效

用mysql客户端连接atlas地址,执行几条SQL观察效果。

mysql -h127.0.0.1 -P1234 -uroot -p123456

连上后先执行:

SELECT @@port;

如果你发现返回值不是atlas的端口,而是某个后端MySQL的真实端口,说明代理已经工作了。接着做一次有说服力的测试:

  • 对从库做标记法,在从库上增加只属于从库的演示库,例如在192.168.1.11的MySQL里执行CREATE DATABASE db_from_1;,在192.168.1.12里执行CREATE DATABASE db_from_2;。
  • 连接atlas执行SHOW DATABASES;,多执行几次,如果能看到db_from_1和db_from_2交替出现,说明读请求确实轮询到了不同从库。
  • 再执行写操作,比如建一个测试表,然后到主库上用SHOW TABLES确认写入已经到达主库。

这个标记法是我在排障时最常用的路子,直观、不易误判。比单纯看代码逻辑更可靠。

3.4 管理接口的常用操作

atlas的管理接口可以实时查看后端状态、连接状态,用于运维管理。连接方式一样是mysql客户端,只是端口换成admin-address。

mysql -h127.0.0.1 -P2345 -uadmin -padmin

进去之后有几个常用命令:

SELECT * FROM backends; SELECT * FROM clients; SELECT * FROM pools;

backends视图可以看到每个后端类型是rw还是ro,状态是up还是down,还能看到连接数分配情况。这个管理接口的价值在排障时尤其明显:连接数打满了,是先看clients里有没有异常的长连接;主从切换后,用backends确认中间件是否发现了拓扑变化;都不需要额外部署监控agent。

4. 生产环境优化与高可用架构

4.1 连接管理与超时参数调优

atlas默认的后端连接管理有一套连接池机制,连接池不是越大越好。我见过一个团队把连接池配得特别大,结果主库连接数直接被打到了上限,应用端的表现反而是更慢。

几个和连接相关的配置项:

  • max-connections:客户端到atlas的最大连接数,要根据实际并发合理设置,超出的连接会被拒绝,不是无限排队。
  • wait-timeout:连接空闲超时时间。如果业务侧有长连接池,这个值要适当放大,或者直接把应用连接池的空闲检测时间调整到小于中间层超时,避免中间层把连接断开又重连,造成无谓开销。
  • backend-connect-timeout:atlas和后端MySQL建立连接的超时时间,网络抖动明显的场景可以适当调大。

参数调优的原则是:先看监控,再动配置。没有监控就乱调,最后都不知道是哪个改动让系统变慢的。

4.2 高可用部署:LVS+多atlas节点

单点atlas始终是个隐患,进程挂了、机器宕机,业务全断。生产中我建议把atlas放在LVS后面做负载均衡和高可用。

部署架构类似:

  • LVS作为虚IP入口,承担流量分发。
  • LVS后面挂两台atlas节点,一主一备,或者同时工作互为主备。
  • 每台atlas分别连接相同的主库和从库集群。

LVS的健康检查脚本可以定期检查atlas的admin端口或者服务端口,探测不到就自动摘除节点。这个方案好在哪里?它把atlas的故障隔离在接入层,应用感知不到具体节点切换。注意LVS本身又成为新的单点,所以LVS也要做双机热备,用Keepalived做VRRP虚IP漂移。

我之前在多个生产环境落地过这套,整体效果稳定。如果团队根本没人会维护LVS,也可以退一步用云负载均衡产品接入,原理一致。

4.3 主从切换后的atlas处理

数据库主从切换后,atlas不会自动感知后端角色变化,这是必须牢记的一个点。比如原来192.168.1.10是主库,现在主库挂了,管理员把192.168.1.11提升为主库。此时atlas配置里写死的proxy-backend-addresses = 192.168.1.10:3306已经指向一个不可用的实例,客户端写请求就会失败。

通常做法是:

  1. 修改atlas配置文件,把新主库地址写到proxy-backend-addresses。
  2. 平滑重启atlas。如果担心连接中断,可以在业务低峰期操作,或者在前面的LVS层先把流量切到备用atlas,再重启另一个。

如果不想频繁改配置文件,可以尝试用管理接口调整backends状态,具体能力受版本限制,建议先小范围验证再依赖。

这里插一句:主从切换最好做成标准操作流程,连atlas配置一起纳入变更单,否则每次切换都靠人肉记住中间件配置,迟早会出事。

4.4 监控与告警的落地思路

atlas的监控不像MySQL本身那么完备,除管理接口的实时状态外,比较有效的方法是在日志输出侧下功夫。

我的做法是:

  • log-level调到一个稳定可用的等级,message级别的日志会包含每一条转发SQL的关键信息,但量很大,生产环境慎重。
  • 把日志目录单独挂盘,避免日志写满根分区。
  • 写脚本定时从admin接口拉取backends和clients信息,上报到监控系统,一旦某后端状态变为down或者连接数突增就告警。
  • 每条SQL转发耗时能在后续版本的日志或优化配置中体现,如果业务有明显的慢查询,优先排查后端数据库和SQL本身,不要只盯着atlas。

5. 常见问题与踩坑实录

5.1 客户端认证失败

典型报错是Access denied for user或者ERROR 1045 (28000)。排查顺序依次是:

  • 配置文件里的pwds字段是否使用的是加密密文,而不是明文。
  • 密码是否在MySQL后端存在,且host匹配了atlas所在机器的IP。
  • atlas里的用户名和密码是否和后端MySQL的实际账号对得上。中间件只是转发认证信息,认证是在后端做的。

有一次我排查半天,最后发现是后端MySQL的账号host限制是192.168.1.%,但atlas连后端时走的源IP是VIP,导致认证被拒,这类网络层问题光看配置很难一眼发现。

5.2 事务中的读请求跑到从库

如果你在应用中用了分布式事务、或者有跨库操作,要留意atlas对BEGIN这类语句的识别。通常START TRANSACTION之后的SQL,中间件能正确路由到主库。但如果业务代码隐性开启了事务而没用标准语句,比如连接池开着autocommit=0,中间件看到的还是一串普通SELECT,就可能路由到从库去。解决方式是规范业务代码里的事务写法,强制要求写库和事务操作使用独立连接,并且显式提交或回滚。

5.3 分表键没走导致全分区扫描

分表规则里定义了user.id.hash,但SELECT * FROM user WHERE name='张三'这种查询没有带ID条件,中间件只能把请求广播到所有分表。数据量小的时候还行,分片一多,性能立刻雪崩。

这类问题的排查思路是:先从慢查询日志看哪些SQL占了大部分耗时,提取WHERE条件,对比分片键是否覆盖;没有覆盖的分片键查询,能改业务SQL就改,不能改就得考虑引入搜索引擎或做宽表冗余。指望中间件帮你全自动处理不存在的。

5.4 网络层TCP连接数过高

atlas在连接管理上对每个客户端的连接会保持一段时间,高并发场景下后端MySQL连接数也会水涨船高。如果发现TCP连接数异常高,用netstat看下是哪些IP在大量建连,再回业务侧看连接池配置是否合理。有些ORM框架默认起来就建一批连接,连接空闲后不主动回收,时间久了就会在atlas上堆积不少CLOSE_WAIT。

处理这类问题我习惯先把应用连接池的最大连接数调到一个业务实际能跑满的值,不要照着示例配置抄一个大的,再配合atlas的wait-timeout回收空闲连接,基本能把连接数控制住。

5.5 日志中常见的几个warning及应对

  • can't connect to backend:atlas连不上某个后端库。优先检查网络联通、后端端口、账号权限。
  • no backend alive:所有后端都不可用,服务基本处于不可用状态。这种告警要最高优先级处理,多半是后端数据库集体故障或者网络分区。
  • too many connections:后端MySQL连接数满了,要么是连接池配置不合理,要么是后端DB本身连接数被打满。先看应用侧能不能回收连接,再考虑扩容。

日志文件默认在log/目录下,建议按天分片切割,否则单文件无限增长会拖垮运维排查。我通常写一个简单的crontab脚本定期归档压缩日志,避免日志盘被写满。

最后再分享一个小技巧

如果你准备在生产环境引入atlas,但心里没底,可以先搭一个最小实验环境:一台主库、一台从库、一台atlas,把读写分离和分表规则都验证一遍,然后用上面的标记法把读写路径彻底搞清楚。我在实际部署中体会到,atlas最怕的不是瓶颈,而是对路由逻辑的不确定性。搞懂了它怎么路由、怎么连接后端,后面调优和排查都是水到渠成的事。这个工具在今天的数据库技术栈里不算是主角,但在没有庞大研发团队的场景下,它依然是一个务实的选择。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询