簡體   English   中英

當 ReplicaSet MongoDB 中的節點出現故障時,更改事件流停止工作

[英]Change event stream stops working when a node fails in ReplicaSet MongoDB

我在使用 mongodb(4.2 版)時遇到問題,特別是更改流功能。

我有一個 ReplicaSet 集群,由 1 個主節點、1 個輔助節點和 1 個仲裁器組成,並且在我的帶有 API mongodb-driver-sync 4.2.0-beta1 的 java 代碼中,我對感興趣的集合有一個 .watch() 進程。 像下面這樣:

MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017,localhost:27018,localhost:27019/?replicaSet=replica");
    MongoDatabase database = mongoClient.getDatabase("test");       
    MongoCollection<Document> collectionStream = database.getCollection("myCollection");
    List<Bson> pipeline = Arrays.asList(Aggregates.match(Filters.and(Filters.in("operationType", Arrays.asList("insert", "update", "replace", "invalidate")))));
    MongoCursor<ChangeStreamDocument<Document>> cursor = collectionStream.watch(pipeline).fullDocument(FullDocument.UPDATE_LOOKUP).iterator();
    ChangeStreamDocument<Document> streamedEvent = cursor.next();
    System.out.println("Streamed event: " + streamedEvent);

基本上,流工作正常。 當插入/更新操作發生時,事件被識別並且文檔被正確地流式傳輸。 但是,當兩個節點之一(主節點或輔助節點,承載數據的節點)出現故障時,觀察者停止流式傳輸任何內容。 更新/插入操作在數據庫上繼續正常,但流被阻止。 只要我重新啟動兩個節點之一,流就會立即正確恢復,並且還會向我顯示以前未流式傳輸的事件。 另一方面,如果仲裁節點出現故障,則流將繼續正常工作。

在我的 rs.conf() 文件下方,如您所見,WriteConcern 參數為 1。

{
"_id" : "replica",
"version" : 31,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
    {
        "_id" : 0,
        "host" : "host1:27017",
        "arbiterOnly" : false,
        "buildIndexes" : true,
        "hidden" : false,
        "priority" : 1000,
        "tags" : {
            
        },
        "slaveDelay" : NumberLong(0),
        "votes" : 1
    },
    {
        "_id" : 1,
        "host" : "host2:27017",
        "arbiterOnly" : false,
        "buildIndexes" : true,
        "hidden" : false,
        "priority" : 1,
        "tags" : {
            
        },
        "slaveDelay" : NumberLong(0),
        "votes" : 1
    },
    {
        "_id" : 4,
        "host" : "host2:27018",
        "arbiterOnly" : true,
        "buildIndexes" : true,
        "hidden" : false,
        "priority" : 0,
        "tags" : {
            
        },
        "slaveDelay" : NumberLong(0),
        "votes" : 1
    }
],
"settings" : {
    "chainingAllowed" : true,
    "heartbeatIntervalMillis" : 500,
    "heartbeatTimeoutSecs" : 3,
    "electionTimeoutMillis" : 3000,
    "catchUpTimeoutMillis" : -1,
    "catchUpTakeoverDelayMillis" : 30000,
    "getLastErrorModes" : {
        
    },
    "getLastErrorDefaults" : {
        "w" : 1,
        "j" : false,
        "wtimeout" : 0
    },
    "replicaSetId" : ObjectId("5f16a4e1e1c622bbea578576")
}}

誰能幫我解決這個問題?

更新:為了解決這個問題,在每個節點的每個 .conf 文件中,我將 replication.enableMajorityReadConcern 設置為 false,以禁用 ReadConcernMajority。 無論如何,按照此設置,通過停止主節點或輔助節點之一,我總是在控制台中收到以下異常:

Exception in thread "main" com.mongodb.MongoExecutionTimeoutException: Error waiting for snapshot not less than { ts: Timestamp(1605805914, 1), t: -1 }, current relevant optime is { ts: Timestamp(1605805864, 1), t: 71 }. :: caused by :: operation exceeded time limit
    at com.mongodb.internal.connection.ProtocolHelper.createSpecialException(ProtocolHelper.java:239)
    at com.mongodb.internal.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:171)
    at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:359)
    at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:280)
    at com.mongodb.internal.connection.UsageTrackingInternalConnection.sendAndReceive(UsageTrackingInternalConnection.java:100)
    at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.sendAndReceive(DefaultConnectionPool.java:490)
    at com.mongodb.internal.connection.CommandProtocolImpl.execute(CommandProtocolImpl.java:71)
    at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:259)
    at com.mongodb.internal.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:202)
    at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:118)
    at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:110)
    at com.mongodb.internal.operation.CommandOperationHelper.executeCommand(CommandOperationHelper.java:345)
    at com.mongodb.internal.operation.CommandOperationHelper.executeCommand(CommandOperationHelper.java:336)
    at com.mongodb.internal.operation.CommandOperationHelper.executeCommandWithConnection(CommandOperationHelper.java:222)
    at com.mongodb.internal.operation.CommandOperationHelper$5.call(CommandOperationHelper.java:208)
    at com.mongodb.internal.operation.OperationHelper.withReadConnectionSource(OperationHelper.java:583)
    at com.mongodb.internal.operation.CommandOperationHelper.executeCommand(CommandOperationHelper.java:205)
    at com.mongodb.internal.operation.AggregateOperationImpl.execute(AggregateOperationImpl.java:189)
    at com.mongodb.internal.operation.ChangeStreamOperation$1.call(ChangeStreamOperation.java:325)
    at com.mongodb.internal.operation.ChangeStreamOperation$1.call(ChangeStreamOperation.java:321)
    at com.mongodb.internal.operation.OperationHelper.withReadConnectionSource(OperationHelper.java:583)
    at com.mongodb.internal.operation.ChangeStreamOperation.execute(ChangeStreamOperation.java:321)
    at com.mongodb.internal.operation.ChangeStreamOperation.execute(ChangeStreamOperation.java:60)
    at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:178)
    at com.mongodb.client.internal.ChangeStreamIterableImpl.execute(ChangeStreamIterableImpl.java:204)
    at com.mongodb.client.internal.ChangeStreamIterableImpl.cursor(ChangeStreamIterableImpl.java:158)
    at com.mongodb.client.internal.ChangeStreamIterableImpl.iterator(ChangeStreamIterableImpl.java:153)
    at com.softstrategy.ProvaWatcher.ProvaWatcherApplication.main(ProvaWatcherApplication.java:34)

另一方面,如果我在默認情況下注釋掉每個文件 .conf 節點中的 enableMajorityReadConcern,則不會出現該異常。

因此,我的問題是以下兩個:

  1. 為什么只有當 ReadConcern 設置為 false 並且當節點 down 是承載數據的節點時才會引發該異常?
  2. 為什么當仲裁節點出現故障時,無論 ReadConcern 設置如何都不會引發該異常?

謝謝!

使用 PSA 架構,如果任一數據承載節點不可用,您將不再擁有大多數數據承載節點。 意思是,您可以使用 w:1 插入,但不能使用 w:majority 插入,並且您將無法執行多數讀取。

根據https://docs.mongodb.com/manual/reference/read-concern-majority/#disable-read-concern-majority使用多數讀取問題更改流:

禁用“多數”讀取問題會禁用對 MongoDB 4.0 及更早版本的更改流的支持。 對於 MongoDB 4.2+,禁用讀取關注“多數”對更改流可用性沒有影響。

https://www.mongodb.com/blog/post/an-introduction-to-change-streams也暗示了這一點

總訂購量

MongoDB 3.6 有一個全局邏輯時鍾,使服務器能夠對分片集群中的所有更改進行排序。 應用程序將始終按照它們應用於數據庫的順序接收更改。

總排序只能通過多數讀取來實現。

如果您希望在數據承載節點之一不可用時更改流以繼續生成事件,請使用 PSS 架構。

您也可以嘗試在 4.2+ 上禁用讀取關注多數,但這還有第一個鏈接中描述的其他問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM