资讯类、内容站的流量特点很一致:读请求是写请求的几十上百倍。一台MySQL扛不住时,主从复制把读压力分给从库,主库专心写,是最省钱的扩容路径——不用换机器、不用改表结构,加从库就行。
前提是主从复制先搭好(这个之前写过:主库开binlog、建同步账号,从库CHANGE MASTER TO)。复制跑通后,剩下的问题只有一个:程序怎么决定这条SQL发给谁。
方案从轻到重三档。第一档代码层分流,最快见效:写操作和强一致读走主库,普通列表、详情页走从库。
// PHP简单分流封装
class Db {
private $master; private $slave;
public function __construct($m, $s) {
$this->master = $m; $this->slave = $s;
}
public function query($sql) {
// 写语句走主库
if (preg_match('/^(insert|update|delete|replace)/i', trim($sql))) {
return $this->master->query($sql);
}
// 读语句走从库,可配多个从库轮询
return $this->slave->query($sql);
}
}
第二档是中间件层,ProxySQL或MySQL Router,程序完全不用改,连接串指向中间件,它自动按语句类型分发。好处是对老代码零侵入,代价是多维护一个组件,它自己也可能成为单点。
这里必须说复制延迟这个坑。主从同步是异步的,高峰期延迟可能到秒级。典型症状:用户发完帖子跳回列表页,自己的帖子看不见,因为写进了主库,列表读的是还没同步完的从库。解法:这类“写完立即读”的关键路径强制走主库。
-- 从库上监控延迟
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master 字段:0为正常
-- 持续大于0说明同步吃紧,高峰期加缓存或再分一个从库
验证分流是否生效:从库上SHOW PROCESSLIST看有没有业务查询进来;主库的processlist里应该只剩写操作。两边的Questions计数器对比一下,比例应该跟预期流量结构一致。
经验之谈:日均PV几十万以下的站,先别急着上读写分离,把慢查询和索引治理好,一台机器绰绰有余。读写分离解决的是“读太多”的量变问题,你的瓶颈要真在数据库,多半先是索引和慢SQL的质变问题,顺序别搞反。
数据来源:MySQL官方手册
A5创业网 版权所有