读写分离延迟处理
class MasterSlaveDB {
private $master; // 主库
private $slave; // 从库
function __construct() {
$this->master = new PDO('mysql:host=master;dbname=test', 'root', '');
$this->slave = new PDO('mysql:host=slave;dbname=test', 'root', '');
}
// 写操作(主库)
function updateUser($id, $name) {
$stmt = $this->master->prepare("UPDATE users SET name = ? WHERE id = ?");
$stmt->execute([$name, $id]);
// 返回版本号用于后续校验
return time();
}
// 读操作 – 方案1: 强制主库读(写后立即读)
function getUserFromMaster($id) {
$stmt = $this->master->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch();
}
// 读操作 – 方案2: 从库读(可能有延迟)
function getUser($id) {
$stmt = $this->slave->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch();
}
// 读操作 – 方案3: 版本号校验重试
function getUserWithRetry($id, $min_version = 0) {
for ($i = 0; $i < 3; $i++) {
$row = $this->getUser($id);
// 检查版本是否足够新
if ($row && $row['updated_at'] >= $min_version) {
return $row;
}
usleep(100000); // 延迟100ms重试
}
// 重试失败,强制主库读
return $this->getUserFromMaster($id);
}
}
$db = new MasterSlaveDB();
// 场景: 更新后立即查询
$version = $db->updateUser(1, 'newname');
// 错误: 从库读可能读到旧数据
$user = $db->getUser(1); // name可能还是旧值
// 正确: 强制主库读
$user = $db->getUserFromMaster(1); // name=newname
// 优化: 版本校验+重试
$user = $db->getUserWithRetry(1, $version); // 确保读到最新数据
大白话: 主从复制有延迟(1–500ms),写后立即读要么读主库,要么校验版本号重试。
输出:
主从延迟: 平均50ms, 最高500ms
场景1(错误): 写主库 -> 读从库 -> 读到旧数据
场景2(安全): 写主库 -> 读主库 -> 读到新数据
场景3(优化): 写主库 -> 校验版本 -> 重试或读主库
方案选择: 强一致读主库, 最终一致读从库




