数据复制架构
数据复制架构
主从复制
主从复制是最常见的数据复制模式。一个主节点处理写操作,多个从节点复制数据并处理读操作。
-- MySQL 主从复制配置示例
-- 主节点配置
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-format = ROW
-- 从节点配置
[mysqld]
server-id = 2
relay-log = relay-bin
read-only = ON
-- 创建复制用户
CREATE USER 'repl'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
// 主从路由的数据源配置
@Configuration
public class DataSourceConfig {
@Bean
@Primary
public DataSource dataSource() {
ReadWriteSplittingDataSource dataSource = new ReadWriteSplittingDataSource();
// 写数据源(主节点)
Map<Object, Object> writeDataSources = new HashMap<>();
writeDataSources.put("write", writeDataSource());
// 读数据源(从节点)
Map<Object, Object> readDataSources = new HashMap<>();
readDataSources.put("read1", readDataSource1());
readDataSources.put("read2", readDataSource2());
dataSource.setWriteDataSourcesMap(writeDataSources);
dataSource.setReadDataSourcesMap(readDataSources);
dataSource.setDefaultTargetDataSource(writeDataSource());
return dataSource;
}
}
多主复制
多主复制允许在多个节点上进行写操作,提高了写入可用性,但需要处理写冲突。
// 冲突检测与解决
@Component
public class ConflictResolver {
// 使用最后写入者胜出策略
public Record resolve(Record record1, Record record2) {
if (record1.getTimestamp().after(record2.getTimestamp())) {
return record1;
} else if (record2.getTimestamp().after(record1.getTimestamp())) {
return record2;
}
// 时间戳相同时使用节点ID排序
return record1.getNodeId().compareTo(record2.getNodeId()) < 0
? record1 : record2;
}
// 使用向量时钟检测因果关系
public boolean isConcurrent(Record record1, Record record2) {
VectorClock clock1 = record1.getVectorClock();
VectorClock clock2 = record2.getVectorClock();
return !clock1.happensBefore(clock2) && !clock2.happensBefore(clock1);
}
}
无主复制
无主复制(如 Dynamo 风格)将数据复制到多个节点,客户端负责协调读写操作。使用 Quorum 机制保证一致性:W + R > N。
// Quorum 写入实现
public void write(String key, Value value) {
List<Node> nodes = getPreferenceNodes(key);
int successCount = 0;
for (Node node : nodes) {
try {
node.write(key, value);
successCount++;
} catch (Exception e) {
log.warn("写入节点失败: {}", node.getId());
}
}
if (successCount < writeQuorum) {
throw new QuorumNotMetException("写入 quorum 未满足");
}
}
一致性模型选择
不同应用场景需要不同的一致性模型。强一致性适合金融交易等场景,最终一致性适合社交媒体等对延迟敏感的场景。选择时需要权衡一致性、可用性和性能。