ホームページ >バックエンド開発 >PHPチュートリアル >データベースシャーディング拡張を実装するための PHP メソッド

データベースシャーディング拡張を実装するための PHP メソッド

PHPz
PHPzオリジナル
2023-05-16 08:36:051427ブラウズ

インターネット時代において、データは企業の最も重要な資産の 1 つになりました。データのストレージと処理に対する需要が増大し続けるにつれ、データベースの拡張は多くの企業にとって避けられない選択となっています。単一のデータベースでは企業のニーズを満たせない場合、データベース シャーディングが効果的な拡張ソリューションになります。

データベース シャーディングとは、データベースを複数の独立したライブラリに水平に分割し、それぞれのライブラリにデータの一部を格納することで、単一ライブラリの負荷を軽減し、システム パフォーマンスを向上させることを指します。実際の応用シーンでは、データベースのシャーディングは垂直シャーディングと水平シャーディングの2つの方式に大別されますが、本記事では主にPHPで実装されている水平シャーディングの拡張方式を紹介します。

  1. データベースの水平シャーディングの基本的な考え方

まず、データを特定のルールに従って異なるシャードに分割する必要があります。ビジネス ニーズに応じて特定のパーティショニング ルールを作成できます。一般的に使用されるルールは次のとおりです:

  • 範囲ベースのシャーディング: シャーディングは特定の列の値に基づいて実行され、各列に格納されるデータ範囲が保証されます。独立;
  • ハッシュベースのシャーディング: 特定の列の値に対してハッシュ操作を実行して値を取得し、その値を異なるシャードに分散して、各シャードにデータが確実に保存されるようにします。シャードはほぼバランスが取れています。

シャードを分割した後、データが配置されているシャードに応じて、アクセスする対応するデータベースを選択できるように接続レイヤーを変更する必要があります。具体的には、接続層は、フラグメント容量、フラグメント開始値、フラグメント終了値などの各フラグメントの関連情報を記録し、ビジネス層が使用するインターフェイスを公開する必要があります。

最後に、ビジネス層は、パーティション化ルールに従って、データベースの読み取りおよび書き込みリクエストを対応するシャードに送信する必要があります。ビジネス層でのデータベース操作は実際には接続層のカプセル化であり、CRUD 操作を実行するにはシャーディング ルールに従って対応するデータベースを選択する必要があります。

  1. PHP によるデータベース シャーディング拡張の実装方法

PHP では、PDO を使用して MySQL データベースのシャーディング拡張を実現できます。具体的には、次の手順に従う必要があります。

2.1 PDO 接続の作成

PDO 接続を作成するときは、いくつかの詳細に注意する必要があります。まず、PDO 接続では、メイン ライブラリの関連構成情報とシャード ライブラリのリストを指定する必要があります。次に、PDO 例外をキャプチャして処理できるように、PDO::ATTR_ERRMODE 属性を PDO::ERRMODE_EXCEPTION に設定する必要があります。最後に、実際の前処理を実現できるように、PDO::ATTR_EMULATE_PREPARES 属性を false に設定する必要があります。

サンプル コードは次のとおりです。

// 主库配置信息
$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 フェーズ コミット プロトコルを利用して、分散トランザクションの一貫性を実現できます。

このうち、最初のフェーズ_Prepare フェーズでは、関連するすべてのシャードに Prepare リクエストを送信して、対応するトランザクション 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();
}
  1. 概要

データベース シャーディングは、データベースの過剰な負荷の問題の解決に役立つ効果的な拡張ソリューションです。単一のデータベースに関する質問です。 PHP では、PDO を使用して MySQL データベースのシャード拡張を実現できます。具体的な操作プロセスには、PDO 接続の作成、シャード クエリの実行、シャード トランザクションの実行が含まれます。実際のアプリケーションでは、分散トランザクションの一貫性だけでなく、データの分割ルールや接続層の変更にも注意を払う必要があります。

以上がデータベースシャーディング拡張を実装するための PHP メソッドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。