sql >> データベース >  >> NoSQL >> MongoDB

MongoDBでロールバックを防ぐ方法

    MongoDBでのレプリケーションには、プライマリメンバーとセカンダリメンバーのアーキテクチャを持つメンバーによるレプリカセットが含まれますが、アービターと呼ばれるデータを保持しないメンバーが含まれる場合もあります。レプリケーションプロセスでは、データがプライマリノードに書き込まれるたびに、変更がoplogファイルに記録され、そこからセカンダリメンバーが同じ変更を適用します。読み取り操作は任意のデータ保持メンバーから実行できるため、一般に高可用性と呼ばれるシナリオが作成されます。

    ただし、場合によっては、セカンダリメンバーがプライマリに追いついて変更を行うことができず、これらの変更が適用される前にプライマリノードに障害が発生した場合、クラスター全体を再同期する必要があります。同じデータ状態にできるようにします。

    ロールバックとは何ですか?

    これはMongoDBの自動フェイルオーバー機能であり、レプリカセットのプライマリノードが失敗する可能性がありますが、変更を加えると、残念ながら、oplogから時間内にセカンダリメンバーに反映されないため、元に戻す必要があります。変更が行われる前のプライマリの状態。

    ロールバックが必要になるのは、ネットワークパーティションなどの理由でプライマリがステップダウンする前に、プライマリがセカンダリメンバーに複製されていない操作の書き込みを受け入れた場合のみです。レプリカセットの大部分が利用可能でアクセス可能なメンバーの1つで書き込み操作を複製できた場合、ロールバックは発生しません。

    MongoDBでのロールバックの背後にある主な理由は、すべてのメンバーのデータの一貫性を維持することです。したがって、プライマリがレプリカセットに再参加するときに、変更がセカンダリメンバーに適用されていない場合は、元に戻されます。失敗する前の状態に。

    ただし、MongoDBではロールバックはまれであるか、回避する必要があります。ロールバックは、大量のデータ損失を引き起こし、その結果、データベースに接続されたアプリケーションの動作に影響を与える可能性があるためです。

    MongoDBロールバックプロセス

    Aをプライマリ、BとCをセカンダリメンバーとして設定された3メンバーのレプリカを考えてみましょう。データをAに入力すると同時に、BとCへのネットワークパーティション分割をトリガーします。このテストでは、MongoDBバージョン4.2とAtlasを使用します。

    まず、mongoシェルでコマンドrs.status()を実行して、レプリカセットのステータスを取得します。

    MongoDB Enterprise Cluster0-shard-0:PRIMARY> rs.status()

    メンバー属性を見ると、次のようなものが表示されます

    "members" : [
    
    {
    
    "_id" : 0,
    
    "name" : "cluster0-shard-00-00-sc27x.mongodb.net:27017",
    
    "health" : 1,
    
    "state" : 2,
    
    "stateStr" : "SECONDARY",
    
    "uptime" : 1891079,
    
    "optime" : {
    
    "ts" : Timestamp(1594826711, 1),
    
    "t" : NumberLong(27)
    
    },
    
    "optimeDurable" : {
    
    "ts" : Timestamp(1594826711, 1),
    
    "t" : NumberLong(27)
    
    },
    
    "optimeDate" : ISODate("2020-07-15T15:25:11Z"),
    
    "optimeDurableDate" : ISODate("2020-07-15T15:25:11Z"),
    
    "lastHeartbeat" : ISODate("2020-07-15T15:25:19.509Z"),
    
    "lastHeartbeatRecv" : ISODate("2020-07-15T15:25:18.532Z"),
    
    "pingMs" : NumberLong(0),
    
    "lastHeartbeatMessage" : "",
    
    "syncingTo" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",
    
    "syncSourceHost" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",
    
    "syncSourceId" : 2,
    
    "infoMessage" : "",
    
    "configVersion" : 4
    
    },
    
    {
    
    "_id" : 1,
    
    "name" : "cluster0-shard-00-01-sc27x.mongodb.net:27017",
    
    "health" : 1,
    
    "state" : 2,
    
    "stateStr" : "SECONDARY",
    
    "uptime" : 1891055,
    
    "optime" : {
    
    "ts" : Timestamp(1594826711, 1),
    
    "t" : NumberLong(27)
    
    },
    
    "optimeDurable" : {
    
    "ts" : Timestamp(1594826711, 1),
    
    "t" : NumberLong(27)
    
    },
    
    "optimeDate" : ISODate("2020-07-15T15:25:11Z"),
    
    "optimeDurableDate" : ISODate("2020-07-15T15:25:11Z"),
    
    "lastHeartbeat" : ISODate("2020-07-15T15:25:17.914Z"),
    
    "lastHeartbeatRecv" : ISODate("2020-07-15T15:25:19.403Z"),
    
    "pingMs" : NumberLong(0),
    
    "lastHeartbeatMessage" : "",
    
    "syncingTo" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",
    
    "syncSourceHost" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",
    
    "syncSourceId" : 2,
    
    "infoMessage" : "",
    
    "configVersion" : 4
    
    },
    
    {
    
    "_id" : 2,
    
    "name" : "cluster0-shard-00-02-sc27x.mongodb.net:27017",
    
    "health" : 1,
    
    "state" : 1,
    
    "stateStr" : "PRIMARY",
    
    "uptime" : 1891089,
    
    "optime" : {
    
    "ts" : Timestamp(1594826711, 1),
    
    "t" : NumberLong(27)
    
    },
    
    "optimeDate" : ISODate("2020-07-15T15:25:11Z"),
    
    "syncingTo" : "",
    
    "syncSourceHost" : "",
    
    "syncSourceId" : -1,
    
    "infoMessage" : "",
    
    "electionTime" : Timestamp(1592935644, 1),
    
    "electionDate" : ISODate("2020-06-23T18:07:24Z"),
    
    "configVersion" : 4,
    
    "self" : true,
    
    "lastHeartbeatMessage" : ""
    
    }
    
    ],

    これにより、レプリカセットの各メンバーのステータスが表示されます。ここで、ノードAの新しいターミナルを開き、20000レコードを入力しました。

    MongoDB Enterprise Cluster0-shard-0:PRIMARY> for (var y = 20000; y >= 0; y--) {
    
        db.mytest.insert( { record : y } )
    
     }
    
    WriteResult({ "nInserted" : 1 })
    
    MongoDB Enterprise Cluster0-shard-0:PRIMARY> db.mytest 2020-07-15T21:28:40.436+2128 I NETWORK  [thread1] trying reconnect to 127.0.0.1:3001 (127.0.0.1) failed
    
    2020-07-15T21:28:41.436+2128 I 
    
    NETWORK  [thread1] reconnect 127.0.0.1:3001 (127.0.0.1) ok
    
    MongoDB Enterprise Cluster0-shard-0:SECONDARY> rs.slaveOk()
    
    MongoDB Enterprise Cluster0-shard-0:SECONDARY> db.mytest.count()
    
    20000

    ネットワークのパーティショニング中に、Aがダウンし、BとCで使用できなくなるため、この場合はBがプライマリとして選択されます。 Aが再参加すると、セカンダリとして追加され、rs.status()コマンドを使用して確認できます。ただし、以下に示すように、ネットワーク分割の前に一部のレコードをメンバーBに複製することができました:(この場合、Bがプライマリになっていることを思い出してください)

    MongoDB Enterprise Cluster0-shard-0:PRIMARY> db.mytest.find({}).count()
    
    12480    

    この数は、Aがダウンする前にBに複製できたドキュメントの数です。

    Bにデータを書き込み、Aがネットワークに参加できるようにすると、Aの変更に気付くことができます

    connecting to: 127.0.0.1:3001/admin
    
    MongoDB Enterprise Cluster0-shard-0:ROLLBACK> 
    
    MongoDB Enterprise Cluster0-shard-0:RECOVERING> 
    
    MongoDB Enterprise Cluster0-shard-0:SECONDARY> 
    
    MongoDB Enterprise Cluster0-shard-0:SECONDARY> 
    
    MongoDB Enterprise Cluster0-shard-0:PRIMARY>

    oplogFetcherセカンダリメンバーを使用して、syncSourceからoplogエントリを同期します。 oplogFetcherは、ソースoplogへのfindメソッドをトリガーし、その後に一連のgetMoresカーソルシリーズが続きます。 Aがセカンダリとして再参加すると、同じアプローチが適用され、述語のタイムスタンプより大きいドキュメントが返されます。 Bの最初のドキュメントがAのoplogの最後のエントリと一致しない場合、Aは強制的にロールバックされます。

    MongoDBでのロールバックデータの復元

    MongDBではロールバックは悪いことではありませんが、ロールバックが頻繁に発生しないように、できる限り努力する必要があります。これは、レプリカセットのメンバー間のデータの一貫性を確保するための安全な自動測定です。ロールバックが発生した場合、状況に対処するためのいくつかの手順を次に示します。

    ロールバックデータ収集

    ロールバックに関するメンバーデータを収集する必要があります。これは、createRollbackDataFilesを有効にして、ロールバックファイルが作成されるようにすることで実行されます(MongoDBバージョン4.0でのみ使用可能)。デフォルトでは、このオプションはtrueに設定されているため、ロールバックファイルは常に作成されます。

    ロールバックファイルはパス/rollback / に配置され、bsondumpツールを使用してBSON形式から変換できるデータが含まれています。人間が読める形式に変換します。

    ロールバックファイルデータを別のデータベースまたはサーバーにロードする

    Mongorestoreは、ロールバックデータファイルのリカバリを可能にするのに役立つMongoDBの重要な側面です。まず、ロールバックファイルを新しいサーバーにコピーしてから、mongorestoreを使用してファイルをサーバーにロードします。 mongorestoreコマンドを以下に示します。

    mongorestore -u <> -p <> -h 127.0.0.1 -d <rollbackrestoretestdb> -c <rollbackrestoretestc> <path to the .bson file> --authenticationDatabase=<database of user>

    不要なデータのクリーンアップと、データのふるい分け

    この手順では、ロールバックファイルから保持するデータと破棄するデータのどちらかを選択するために、慎重に判断する必要があります。すべてのロールバックファイルデータをインポートすることをお勧めします。この決定ポイントにより、このステップはデータ回復の最も難しいステップになります。

    Primaryをクラスターとして使用してデータをインポートする

    mongorestoreとmongodumpを使用してクレンジングされたデータをダウンロードし、最後のステップを開始します。その後、データを元の本番クラスターに再インポートします。

    MongoDBロールバックの防止

    MongoDBの使用時にデータのロールバックが発生しないようにするには、次のようにします。

    すべての投票メンバー「MAJORITY」の実行

    これは、w:多数の書き込み懸念を使用して実行できます。これは、Mongodインスタンスの特定のタグへの書き込み操作を可能にするオプション要求の確認応答を行う権限があります。これは、wオプションの後にタグを使用することで実現できます。ロールバックを防ぐために、MongoDBのすべての投票メンバーはジャーナルを有効にし、w:マジョリティ書き込みの懸念を使用します。これにより、ロールバックが発生する前にマジョリティがレプリカノードに書き込みおよび設定できるようになります。また、レプリカセットで書き込み操作を伝播した後、クライアントが確認応答を確実に受信できるようにします。

    ユーザー操作

    MongoDBの更新バージョン、つまりバージョン4.2には、ロールバックが発生した場合に実行中のすべての操作をシャットダウンする機能があります。

    インデックスビルド

    MongoDB機能互換性バージョン(fcv)のバージョン4.2「4.2」は、ロールバックが実行される前に、構築および終了されるすべての進行中のインデックスを待機できます。場所。ただし、バージョン4.0は進行中の継続を待機し、バックグラウンドインデックスを構築するため、ロールバックの可能性が高くなります。

    サイズと制限

    MongoDBのバージョン4.0には、進行中のバックグラウンドインデックスのビルド時にロールバックできる特定のデータの制限がリストされていません。

    結論

    MongoDBのロールバックは、MongoDBを防止する方法を知らずにMongoDBを使用している人によく見られる現象です。 MongoDBでのロールバックを回避するための安全な方法と方法のいくつかに熱心に従い、それを順守すれば、ロールバックを防ぐことができます。全体として、予防可能な問題を回避するために、MongoDBの最新バージョンにアップグレードすることを常にお勧めします。


    1. Celery for Realtime、Geventを使用した同期外部APIクエリの使用

    2. Redisのインストール方法

    3. 最高のMongoDBGUIはどれですか? —2019アップデート

    4. Ansibleを使用したMongoDBのデプロイとメンテナンス