인터넷 시대에 데이터는 기업의 가장 중요한 자산 중 하나가 되었습니다. 데이터 저장 및 처리에 대한 수요가 지속적으로 증가함에 따라, 데이터베이스 확장은 많은 기업에서 불가피한 선택이 되었습니다. 단일 데이터베이스가 기업의 요구 사항을 충족할 수 없는 경우 데이터베이스 샤딩이 효과적인 확장 솔루션이 됩니다.
데이터베이스 샤딩은 데이터베이스를 여러 개의 독립적인 라이브러리로 수평적으로 분할하는 것을 의미하며, 각 라이브러리는 데이터의 일부를 저장하여 단일 라이브러리의 부하를 줄이고 시스템 성능을 향상시킵니다. 실제 애플리케이션 시나리오에서 데이터베이스 샤딩은 일반적으로 수직 샤딩과 수평 샤딩의 두 가지 방법으로 구분됩니다. 이 기사에서는 주로 PHP에서 구현하는 수평 샤딩 확장 방법을 소개합니다.
먼저, 특정 규칙에 따라 데이터를 여러 샤드로 나누어야 합니다. 비즈니스 요구에 따라 특정 파티셔닝 규칙을 공식화할 수 있습니다. 일반적으로 사용되는 규칙은 다음과 같습니다.
// 主库配置信息 $masterConfig = [ 'dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=test', 'username' => 'root', 'password' => 'root', ]; // 分片库列表 $shardConfigList = [ [ 'dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=test_shard_0', 'username' => 'root', 'password' => 'root', ], [ 'dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=test_shard_1', 'username' => 'root', 'password' => 'root', ], ]; // 创建PDO连接 $pdo = new PDO($masterConfig['dsn'], $masterConfig['username'], $masterConfig['password'], [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false, ]);2.2 샤딩된 쿼리 실행애플리케이션에서 데이터베이스 작업을 수행할 때 파티셔닝 규칙에 따라 데이터를 해당 샤드에 할당해야 합니다. 일반적으로 샤딩된 라이브러리 세트의 구조는 동일하며 데이터만 다릅니다. 따라서 샤드 쿼리를 수행할 때 먼저 메인 라이브러리로부터 샤드 정보를 획득하고, 샤드 정보를 기반으로 해당 샤드 라이브러리에 쿼리 요청을 전달할 수 있습니다. 샘플 코드는 다음과 같습니다.
// 获取分片信息 $sql = 'SELECT * FROM `shard_info` WHERE shard_id = ?'; $stmt = $pdo->prepare($sql); $stmt->execute([$shardId]); $info = $stmt->fetch(PDO::FETCH_ASSOC); if (!$info) { throw new RuntimeException('Shard not found'); } // 创建分片PDO连接 $pdoShard = new PDO($info['dsn'], $info['username'], $info['password'], [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false, ]); // 执行查询 $sql = 'SELECT * FROM `table` WHERE `key` = ?'; $stmt = $pdoShard->prepare($sql); $stmt->execute([$key]); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);2.3 샤딩 트랜잭션 실행분산 트랜잭션을 수행할 때 관련된 여러 샤드의 작업을 전체적으로 처리해야 합니다. 특히 분산 트랜잭션의 일관성을 달성하기 위해 2단계 커밋 프로토콜을 활용할 수 있습니다. 그 중 첫 번째 단계_준비 단계에서는 해당 트랜잭션 ID를 얻기 위해 관련된 모든 샤드에 준비 요청을 보내야 합니다. 모든 샤드가 성공적인 응답을 반환한 후 커밋/중단 요청을 모든 샤드에 보내 트랜잭션을 커밋하거나 롤백해야 합니다. 샘플 코드는 다음과 같습니다.
// 开始分布式事务 $pdo->beginTransaction(); try { // 准备分片事务 $xid = uniqid(); $prepares = []; foreach ($shardConfigList as $shardConfig) { $pdoShard = new PDO($shardConfig['dsn'], $shardConfig['username'], $shardConfig['password'], [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false, ]); $pdoShard->beginTransaction(); $stmt = $pdoShard->prepare('INSERT INTO `table` (`key`, `value`) VALUES (?, ?)'); $stmt->execute([$key, $value]); $prepares[] = [$pdoShard, $xid]; } // 提交分片事务 foreach ($prepares as [$pdoShard, $xid]) { $stmt = $pdoShard->prepare('PREPARE TRANSACTION ?'); $stmt->execute([$xid]); } foreach ($prepares as [$pdoShard, $xid]) { $stmt = $pdoShard->prepare('COMMIT PREPARED ?'); $stmt->execute([$xid]); } // 提交整个事务 $pdo->commit(); } catch (Exception $ex) { // 回滚分片事务 foreach ($prepares as [$pdoShard, $xid]) { $stmt = $pdoShard->prepare('ROLLBACK PREPARED ?'); $stmt->execute([$xid]); } // 回滚整个事务 $pdo->rollback(); }
위 내용은 데이터베이스 샤딩 확장을 구현하는 PHP 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!