Table Store:大量の構造化データのリアルタイムバックアップ実戦


データバックアップの概要


情報技術とデータ管理の分野では、バックアップとはファイルシステムやデータベースシステムのデータをコピーし、災害やエラー操作が発生すると、システムの有効なデータと正常な動作を便利かつタイムリーに回復することを意味します.実際のバックアップでは、重要なデータを3つ以上作成し、後で保存するために異なる場所に配置してバックアップすることが望ましい.
バックアップには2つの異なる目的があります.主な目的は、データが削除されても破損しても、データが失われた後にデータを復元することです.バックアップの2つ目の目的は、ユーザー定義のデータ保存ポリシーに基づいて、通常、バックアップ・アプリケーションでバックアップにどのくらいの時間がかかるデータ・コピーを構成するより早い時間からデータをリカバリすることです.
バックアップ・システムには、保存に値すると思われるすべてのデータのコピーが少なくとも1つ含まれるため、データ・ストレージに対する要求が高くなる可能性があります.このストレージ領域を組織し、バックアップ・プロセスを管理することは複雑なタスクである可能性があります.現在、バックアップに使用できるさまざまなタイプのデータストレージデバイスが多く、地理的冗長性、データセキュリティ、移植性を提供するために、さまざまな方法でこれらのデバイスを手配することもできます.
データを格納場所に送信する前に、それらを選択、抽出、操作します.現在、開いているファイル(open files)の処理やリアルタイムのデータソースの最適化、圧縮、暗号化、重複データの削除など、バックアッププロセスを最適化するためのさまざまな技術があります.各バックアップ・スキーマには、バックアップ中のデータの信頼性を検証するための演習プロセスが含まれます.さらに重要なのは、バックアップ・スキーマに関連する制限と人為的な要因を認識することです.

Table Storeバックアップ需要分析


ストレージシステムにとって、データの安全信頼性は常に第一位であり、データのできるだけ高い信頼性を保障するには、2つの面から保障する必要があります.
  • ストレージシステム自体のデータ信頼性:テーブルストレージ(Table Store)はアリクラウドが独自に開発した大量構造化データストレージ向けのServerless NoSQLマルチモデルデータベースであり、99.9999999%のデータ信頼性保証を提供しており、業界では非常に高い基準となっている.
  • 誤操作後にデータを復旧できる:誤操作は永遠に避けられない.誤操作が発生した場合に速やかに復旧できるようにするには、バックアップデータが必要である.バックアップの場合、2つのシナリオがあります.1つは、同じ都市や異郷の災害を導入することです.このコストが高く、社会基盤情報や金融情報に多く使用されます.もう1つは、データをより安価なシステムにバックアップし、万一誤操作が発生した場合、リカバリする方法があればよい.一般的に、アリクラウドOSSなどのファイルストレージシステムを選択することができます.

  • Table Storeバックアップ・リカバリ・スキームの概要


    下図はTable Storeバックアップ・リカバリの論理構造図で、フルインクリメンタル一体のチャネル・サービスに基づいて、リアルタイムのインクリメンタル・バックアップ能力と秒レベルのリカバリ能力を備えたデータ・バックアップとデータ・リカバリ・スキームのセットを容易に構築できます.バックアップとリカバリの計画を事前に構成すれば、バックアップ・リカバリ・システム全体を完全に自動化できます.

    Table Storeバックアップ復旧方案実戦


    現在、表ストレージは公式のバックアップとリカバリ機能を発売していないが、筆者はstep-by-stepの表ストレージベースのチャネルサービス設計を独自のバックアップリカバリスキームにし、実戦ステップはバックアップとリカバリの2つの部分に分けられる.
    1.バックアップ
  • 準備フェーズ:バックアップ対象のデータソースとバックアップの目的ソースを特定する必要があり、今回の実戦ではTable StoreのテーブルとOSSのBucketにそれぞれ対応している.
  • バックアップ計画とポリシーの決定
  • チャネルサービスSDKを使用したコード作成
  • バックアップポリシーの実行とバックアッププロセスの監視
  • 2.リカバリ
  • ファイル復旧の実行
  • バックアップ計画とポリシーの決定


    バックアップ・ポリシーには、バックアップの内容、バックアップ時間、およびバックアップ方法を決定する必要があります.現在一般的なバックアップ・ポリシーには、主に次のようなものがあります.
  • フルバックアップ(Full Backup):ハードディスクまたはデータベース内のすべてのファイル、フォルダまたはデータを一度にコピーします.
  • インクリメンタルバックアップ(Incremental Backup):前回のフルバックアップまたはインクリメンタルバックアップ後に更新されたデータのバックアップ.
  • 差分バックアップ(Differential Backup):フルバックアップ実行後にファイルを変更するバックアップを提供する.
  • オプションバックアップ:システムデータの一部をバックアップする.
  • コールドバックアップ:システムがダウンタイムまたはメンテナンス状態のバックアップ.この場合、バックアップされたデータは、システムの期間のデータと完全に一致する必要があります.
  • ホット・バックアップ:システムが正常に稼働している状態でのバックアップ.この場合、システム内のデータは随時更新される可能性があるため、バックアップされたデータはシステムの実際のデータに対して一定の遅延がある可能性があります.

  • 今回の実戦では、バックアップ計画と戦略の選択は以下の通りである(ここでは、自分のニーズに合わせてカスタマイズし、チャネルサービスのSDKを利用してニーズを満たすことができる).
  • バックアップ内容:Table Storeデータシート
  • バックアップ時間:
  • フルバックアップは定期的に実行される(時間調整可能、デフォルトは1週間).
  • インクリメンタルバックアップは構成によって定期的に実行され、テーブルに格納されたチャネルサービスはデータの厳格な秩序性を保障し、各インクリメンタルファイルはストリーミングappendであり、いつでも消費される.

  • バックアップ方式:フルバックアップ+インクリメンタルバックアップ、ホットバックアップ.

  • チャネルサービスSDKを使用したコード作成


    この部分はコードクリップの形式に合わせて説明しますが、詳細なコードは後でオープンソースになります(リンクは本稿で更新されます)、楽しみにしてください.実戦を行う前に、チャネルサービスJava SDKの使用文書を読むことをお勧めします.
  • 全量+インクリメンタルタイプのTunnelを作成します.ここではSDKまたは公式サイトコンソールを使用して作成できます.  
  • private static void createTunnel(TunnelClient client, String tunnelName) {
        CreateTunnelRequest request = new CreateTunnelRequest(TableName, tunnelName, TunnelType.BaseAndStream);
        CreateTunnelResponse resp = client.createTunnel(request);
        System.out.println("RequestId: " + resp.getRequestId());
        System.out.println("TunnelId: " + resp.getTunnelId());
    }
  • チャネルサービス自動化データ処理フレームワークを知るチャネルサービスの迅速な開始において、ユーザはデータを処理するプロセス関数とshutdown関数を入力するだけで自動化されたデータ処理を完了できることがわかる.プロセス関数のエントリにはリストが付きますが、StreamRecordパッケージはTable Storeの各行のデータで、Recordのタイプ、プライマリ・キー列、プロパティ列、ユーザーがRecordに書き込むタイムスタンプなどが含まれています.
  • Table Store各行データの永続化フォーマットを設計今回の実戦ではCSVファイルフォーマットを使用しています.もちろんpbやその他のフォーマットも使用できます.CSVの利点は可読性が強く、各行のデータはCSVファイルの1行に対応しています.永続化フォーマットは下図のようにCSVファイルは4列、TimeStamp列はTable Storeにデータが書き込まれたタイムスタンプ(全量で0、インクリメンタルバックアップは具体的なタイムスタンプ)です.RecordTypeはデータ行の操作タイプ(PUT,UPDATE,DELETE)であり、PrimaryKeyはプライマリ・キー列のJSON文字列、RecordColumnsは属性列のJSON文字列である.

  • 変換部のコアコードは以下のコード断片を参照し、筆者がこの部分を処理するのはunivocity-parsers(CSV)とGsonライブラリであり、いくつかの点に特に注意しなければならない.Gson逆シーケンス化LongタイプはNumberタイプに変わり,進捗が失われる可能性があり,いくつかの解決策があり,筆者はそれをStringタイプシーケンス化に変えることを採用している.2). binaryタイプのデータの特殊な処理について,筆者はbase 64の符号化を行った.3). OSSに直接ストリーミングすることで、ローカル持続性の消費を削減できます.
    this.gson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new ByteArrayToBase64TypeAdapter())
               .setLongSerializationPolicy(LongSerializationPolicy.STRING).create();
    // ByteArrayOutputStream ByteArrayInputStream array.copy,  NIO channel.
    public void streamRecordsToOSS(List records, String bucketName, String filename, boolean isNewFile) {
       if (records.size() == 0) {
           LOG.info("No stream records, skip it!");
           return;
       }
       try {
           CsvWriterSettings settings = new CsvWriterSettings();
           ByteArrayOutputStream out = new ByteArrayOutputStream();
           CsvWriter writer = new CsvWriter(out, settings);
           if (isNewFile) {
               LOG.info("Write csv header, filename {}", filename);
               List headers = Arrays.asList(RECORD_TIMESTAMP, RECORD_TYPE, PRIMARY_KEY, RECORD_COLUMNS);
               writer.writeHeaders(headers);
               System.out.println(writer.getRecordCount());
           }
           List totalRows = new ArrayList();
           LOG.info("Write stream records, num: {}", records.size());
           for (StreamRecord record : records) {
               String timestamp = String.valueOf(record.getSequenceInfo().getTimestamp());
               String recordType = record.getRecordType().name();
               String primaryKey = gson.toJson(
                   TunnelPrimaryKeyColumn.genColumns(record.getPrimaryKey().getPrimaryKeyColumns()));
               String columns = gson.toJson(TunnelRecordColumn.genColumns(record.getColumns()));
               totalRows.add(new String[] {timestamp, recordType, primaryKey, columns});
           }
           writer.writeStringRowsAndClose(totalRows);
    
           // write to oss file
           ossClient.putObject(bucketName, filename, new ByteArrayInputStream(out.toByteArray()));
       } catch (Exception e) {
           e.printStackTrace();
       }
    }

    バックアップ・ポリシーの実行とバックアップ・プロセスの監視

  • チャネルサービスの自動化データフレームワークを実行し、前ステップで設計したバックアップポリシーコードをマウントする.
  • public class TunnelBackup {
        private final ConfigHelper config;
        private final SyncClient syncClient;
        private final CsvHelper csvHelper;
        private final OSSClient ossClient;
    
        public TunnelBackup(ConfigHelper config) {
            this.config = config;
            syncClient = new SyncClient(config.getEndpoint(), config.getAccessId(), config.getAccessKey(),
                config.getInstanceName());
            ossClient = new OSSClient(config.getOssEndpoint(), config.getAccessId(), config.getAccessKey());
            csvHelper = new CsvHelper(syncClient, ossClient);
        }
    
        public void working() {
            TunnelClient client = new TunnelClient(config.getEndpoint(), config.getAccessId(), config.getAccessKey(),
                config.getInstanceName());
            OtsReaderConfig readerConfig = new OtsReaderConfig();
            TunnelWorkerConfig workerConfig = new TunnelWorkerConfig(
                new OtsReaderProcessor(csvHelper, config.getOssBucket(), readerConfig));
            TunnelWorker worker = new TunnelWorker(config.getTunnelId(), client, workerConfig);
            try {
                worker.connectAndWorking();
            } catch (Exception e) {
                e.printStackTrace();
                worker.shutdown();
                client.shutdown();
            }
        }
    
        public static void main(String[] args) {
            TunnelBackup tunnelBackup = new TunnelBackup(new ConfigHelper());
            tunnelBackup.working();
        }
    }
  • バックアッププロセスをモニタリングするモニタリングは、テーブルストレージコンソールまたはDescribeTunnelインタフェースで行うことができ、DescribeTunnelインタフェースは、現在のTunnelの下にある各ChannelのClient(カスタマイズ可能)、消費合計行数、消費ビットポイントなどの情報をリアルタイムで取得することができる.例えば、ユーザーは午後2時-3時のデータを同期する必要があり、DescribeTunnelが取得した消費サイトが午後2時半であれば、バックアップが半分になったことを示し、取得した消費サイトが午後3時であれば、2時-3時のデータのバックアップが完了したことを表す.

  • ファイルリカバリの実行


    データバックアップが完了すると、必要に応じてフル・リカバリと一部のデータ・リカバリを行い、RTOを削減できます.データをリカバリする際には、リカバリのパフォーマンスを最適化するためのいくつかの方法があります.
  • OSSからダウンロードする場合は、ストリーミングダウンロードまたはスライスダウンロードを使用して、必要に応じて同時ダウンロードを増やすことができます.
  • Table Storeに書き込む場合は、同時BatchWrite方式を使用できます.下の図はRestoreのインスタンスコード(いくつかの詳細を省略)で、まず必要に応じてダウンロードするファイル名(バックアップポリシーに対応)を算出し、OSSのストリーミングダウンロードで対応するファイルを読み出し、最後にTableStoreのリカバリテーブルに同時のBatchWrite方式で書き込む.
  • public class TunnelRestore {
        private ConfigHelper config;
        private final SyncClient syncClient;
        private final CsvHelper csvHelper;
        private final OSSClient ossClient;
    
        public TunnelRestore(ConfigHelper config) {
            this.config = config;
            syncClient = new SyncClient(config.getEndpoint(), config.getAccessId(), config.getAccessKey(),
                config.getInstanceName());
            ossClient = new OSSClient(config.getOssEndpoint(), config.getAccessId(), config.getAccessKey());
            csvHelper = new CsvHelper(syncClient, ossClient);
        }
    
        public void restore(String filename, String tableName) {
            csvHelper.parseStreamRecordsFromCSV(filename, tableName);
        }
    
        public static void main(String[] args) {
            TunnelRestore restore = new TunnelRestore(new ConfigHelper());
            restore.restore("FullData-1551767131130.csv", "testRestore");
        }
    }

    まとめ


    本稿ではまずTable Storeバックアップの必要性を紹介し,次に表に格納されたチャネルサービスを用いたデータバックアップとリカバリの原理を紹介し,最後に実際のコードフラグメントと結びつけてTabel Storeデータバックアップリカバリスキームの構築方法について述べた.

    リファレンスリンク

  • 4 Steps to Create Your Backup Plan
  • https://en.wikipedia.org/wiki/Backup

  • 作者:琸然
    原文を読む
    本文は雲栖コミュニティのオリジナル内容で、許可を得ずに転載してはならない.