很多时候,我们的系统性能瓶颈其实就是数据库。在业务中,读取数据的操作通常比写入多得多,有时候甚至能达到十倍以上。如果主库的能力有限,整个系统就会变得很慢。 想让系统变快,就得先找出问题所在。从连接数据库开始,网络传输、身份验证、权限检查、SQL 解析这些步骤都在消耗时间。还有一个隐藏的问题是,磁盘 I/O 被频繁地使用,热点数据被反复写入硬盘。主库压力太大时,数据一致性、高可用性和备份这些问题就会变得更加复杂。 为了提升性能,我们可以采用一些策略: 1. 连接池:把大量的数据库连接提前准备好,这样就不用每次都进行三次握手,提高了效率。 2. 异步 IO:让请求发送出去后线程还能继续处理其他任务,不用等待结果回来。 3. SQL 预编译:跳过词法分析、权限检查这些步骤,直接执行核心操作。单条语句的执行时间平均能降低30%以上。 4. 读写分离:把读操作分散到从库上,水平扩容从库就能线性提升读性能。主从复制还能解决单点故障问题。 主从复制不仅是为了分摊压力,还保证了数据一致性。半同步复制确保主库写入后至少能同步到一个从库一次。读写分离时最好还是读主库的数据,避免从库负载突然增加。 缓存层也非常重要。MySQL 自带了 InnoDB Buffer Pool 把热点数据缓存在内存里,但缺点是受 LRU 算法控制的业务不可控。Redis 和 Memcached 这类全内存缓存能大大提升读写速度,还可以通过 RDB 或 AOF 持久化到磁盘。 系统引入 Redis 后,数据状态会变得复杂:有的只在 MySQL 里有,有的只在 Redis 里有。为了保持数据一致性,核心策略是以 MySQL 为准绳,Redis 只做快速获取。同步失败就回滚或者标记为脏数据。 读操作优先访问 Redis,如果没找到再去查 MySQL。写操作可以根据需求选择强一致或最终一致的策略。如果宕机风险由业务来承担。 主从复制原理其实就是把更新操作从主库传到从库。DML 操作先写入 binlog,然后从库拉取 binlog 写入 relay log,最后重放完成同步。binlog 和 redolog 配合保证了 crash-safe。 零侵入同步工具 go-mysql-transfer 可以配置热点表和字段,用 Lua 脚本过滤需要同步的行。第一次全量导出后就是增量同步了。 缓存异常包括穿透、击穿和雪崩:穿透是大量请求不存在的 key 导致压力全灌 MySQL;击穿是热点 key 过期瞬间大量并发请求未命中;雪崩是大量 key 同时失效导致系统瘫痪。 对于穿透问题可以写入 <key, nil> 并设置短过期时间来过滤;布隆过滤器也能提前拦截不可能存在的 key。击穿问题可以通过分布式锁控制并发回源并设置长过期时间;雪崩问题可以随机设置过期时间错开高峰或者使用 Redis 高可用集群来保证服务不宕。 最后把所有策略串成一个闭环:连接池、读写分离、缓存同步、异常防护这些环节都控制好了,性能提升就不再是玄学了。