亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原(yuan)創

MongoDB 中的觀察者模式

2024-10-17 09:34:43
4
0

基本概念

觀(guan)察(cha)者模式(shi)是一種行為型(xing)設計(ji)模式(shi),它定義了一種一對(dui)多的(de)依(yi)賴關系(xi),當一個(ge)對(dui)象的(de)狀態(tai)發生改變(bian)時,其所有依(yi)賴者都會收到(dao)通知并自動更新。

當對(dui)象間存在(zai)一對(dui)多(duo)關(guan)系時(shi)(shi),則(ze)(ze)使用(yong)觀(guan)察(cha)者模式。比如,當一個對(dui)象被修改時(shi)(shi),則(ze)(ze)會(hui)自動(dong)通知依賴它的對(dui)象。觀(guan)察(cha)者模式屬于行為型模式。

在 MongoDB 中,Observer 模式使用在對請求(qiu)的監聽上。當有一條變更操作(zuo)發生時(shi),除了對存儲引擎進行數(shu)據寫入外,還可能執行以下額(e)外的操作(zuo):

  1. 如果運行在副本集模式下,還要寫 oplog。
  2. 如果修改了 admin 庫下的 system.users、system.roles 系統表,還需要通知 authManager 進行權限更新。
  3. 如果修改了 cache.chunks.xxx 路由緩存表,還需要進行本地路由刷新。
  4. ...

以(yi)(yi)上這些(xie)操(cao)作(zuo)(zuo)都可以(yi)(yi)按(an)功能(neng)模塊劃分出具(ju)體的(de) observer,當(dang)有變更(geng)操(cao)作(zuo)(zuo)發(fa)生時(shi),會(hui)通知這些(xie) observer 執(zhi)行對(dui)應的(de)操(cao)作(zuo)(zuo)。

實現方式

類型定義

observer.png

OpObServer 是(shi)一個抽象類,其(qi)主要(yao)的實(shi)現包括(kuo):

  • OpObserverImpl: 實現了常見的 DDL、DML 的處理方式,包括如何調用接口寫 oplog。
  • OpObserverShardingImpl: 繼承自 OpObserverImpl,并實現了 shardSever 之間遷移數據時,如何處理插入、更新、刪除的數據處于正在遷移的 chunk 中的情況。
  • AuthOpObserver: 實現了對 system.users、system.roles 等系統表進行變更時的處理流程。
  • ConfigServerOpObserver: 實現了在 configServer 節點上對 config 庫執行變更時的處理流程。
  • ShardServerOpObserver: 實現了 shardServer 節點上對 cache.chunks.xxx 路由緩存表執行變更時的處理流程。
  • OpObserverRegistry: OpObserver 注冊器,內部使用數組存儲,當有監聽的動作發生時,會循環調用數組中每個 OpObserver 的方法。

調用流程

在 mongod 節(jie)點(副(fu)本集、單節(jie)點、shardServer、configServer)啟動時(shi),會根據運行配置(zhi)注冊(ce)多個 OpObserver 到 OpObserverRegistry 中,而 OpObserverRegistry 存放(fang)在全局唯一的 ServerContext 結構中。參考(kao) _initAndListen 的實現(xian):

auto serviceContext = getGlobalServiceContext();

    serviceContext->setFastClockSource(FastClockSourceFactory::create(Milliseconds(10)));
    // 分配 opObserverRegistry
    auto opObserverRegistry = stdx::make_unique<OpObserverRegistry>();
    // 注冊 OpObserver
    opObserverRegistry->addObserver(stdx::make_unique<OpObserverShardingImpl>());
    opObserverRegistry->addObserver(stdx::make_unique<AuthOpObserver>());

    if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) {
        // shardServer 節點上,注冊 ShardServerOpObserver
        opObserverRegistry->addObserver(stdx::make_unique<ShardServerOpObserver>());
    } else if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
        // configServer 節點上,注冊 ConfigServerOpObserver
        opObserverRegistry->addObserver(stdx::make_unique<ConfigServerOpObserver>());
    }
    setupFreeMonitoringOpObserver(opObserverRegistry.get());

    serviceContext->setOpObserver(std::move(opObserverRegistry));

當有監(jian)聽的動作發生時,會調用 ServerContext 結構中的 OpObserverRegistry 對應的方法。以(yi) CollectionImpl::insertDocuments 插入動作為例:

getGlobalServiceContext()->getOpObserver()->onInserts(
        opCtx, ns(), uuid(), begin, end, fromMigrate);

Observer 操作的一致性

以(yi) insert 操(cao)作為例,對應的 observer 的動作需(xu)要與其保持(chi)一致。即同時提(ti)交或者回(hui)滾。

有些 observer 動作(zuo)是可以(yi)利用存儲引擎的事務原子性(xing)來保證(zheng)的,比如 oplog 的提(ti)交。

有些 observer 動作(zuo)不(bu)會修改(gai)(gai)存(cun)儲引擎數據,只(zhi)是會修改(gai)(gai)內存(cun)狀態,比(bi)如 AuthOpObserver 的(de)權限更新動作(zuo)。對于(yu)這(zhe)些可以利用 WiredTigerRecoveryUnit 的(de) Change 機制,在(zai) WiredTigerRecoveryUnit 進(jin)行事務(wu)提交(jiao)或者回滾之后,調(diao)用 Change 中傳入(ru)的(de) rollback 和 commit 回調(diao)函數完成相應(ying)的(de)操作(zuo)。

不過 Change 機制不和對應的事務一起保證原子性。可能在事務提交之后馬上斷電,沒有執行對應的 Change 回調函數。以 AuthOpObserver 為例,可能修改了 admin.system.users 表并記錄了 oplog,但是沒有來得及更新內存結構就宕機了。
不過這種情況問題不大,因為節點重啟之后,會根據(ju)磁盤上最新(xin)的一致性數據(ju)重新(xin)構建內存數據(ju)。

0條評論
0 / 1000
彭振翼
6文(wen)章數
1粉絲(si)數
彭振翼
6 文章 | 1 粉絲
原創

MongoDB 中的觀察者模式

2024-10-17 09:34:43
4
0

基本概念

觀察者模式是一(yi)(yi)種行(xing)為型設計模式,它定義了一(yi)(yi)種一(yi)(yi)對多的依賴關系(xi),當一(yi)(yi)個對象的狀態(tai)發生(sheng)改變時,其所有依賴者都會收到通知并自動更新。

當對象間存在(zai)一對多關系時(shi),則使用(yong)觀察者(zhe)模式。比如,當一個對象被修改時(shi),則會自(zi)動(dong)通知依賴它的(de)對象。觀察者(zhe)模式屬(shu)于行為(wei)型模式。

在 MongoDB 中,Observer 模式使用(yong)在對(dui)(dui)請求的(de)監聽上。當有一條(tiao)變(bian)更操作(zuo)發生(sheng)時,除了(le)對(dui)(dui)存儲引擎進行數據寫入外,還可能執(zhi)行以下額(e)外的(de)操作(zuo):

  1. 如果運行在副本集模式下,還要寫 oplog。
  2. 如果修改了 admin 庫下的 system.users、system.roles 系統表,還需要通知 authManager 進行權限更新。
  3. 如果修改了 cache.chunks.xxx 路由緩存表,還需要進行本地路由刷新。
  4. ...

以上這些操作(zuo)都可以按功能模塊劃(hua)分出具(ju)體的(de) observer,當有變更操作(zuo)發生時,會通知(zhi)這些 observer 執行對應的(de)操作(zuo)。

實現方式

類型定義

observer.png

OpObServer 是一(yi)個抽象類,其(qi)主(zhu)要的實現包括:

  • OpObserverImpl: 實現了常見的 DDL、DML 的處理方式,包括如何調用接口寫 oplog。
  • OpObserverShardingImpl: 繼承自 OpObserverImpl,并實現了 shardSever 之間遷移數據時,如何處理插入、更新、刪除的數據處于正在遷移的 chunk 中的情況。
  • AuthOpObserver: 實現了對 system.users、system.roles 等系統表進行變更時的處理流程。
  • ConfigServerOpObserver: 實現了在 configServer 節點上對 config 庫執行變更時的處理流程。
  • ShardServerOpObserver: 實現了 shardServer 節點上對 cache.chunks.xxx 路由緩存表執行變更時的處理流程。
  • OpObserverRegistry: OpObserver 注冊器,內部使用數組存儲,當有監聽的動作發生時,會循環調用數組中每個 OpObserver 的方法。

調用流程

在(zai) mongod 節點(副本集、單節點、shardServer、configServer)啟動時(shi),會根據(ju)運行(xing)配置(zhi)注冊多個 OpObserver 到(dao) OpObserverRegistry 中(zhong),而 OpObserverRegistry 存放在(zai)全局(ju)唯(wei)一的(de) ServerContext 結構中(zhong)。參考 _initAndListen 的(de)實現(xian):

auto serviceContext = getGlobalServiceContext();

    serviceContext->setFastClockSource(FastClockSourceFactory::create(Milliseconds(10)));
    // 分配 opObserverRegistry
    auto opObserverRegistry = stdx::make_unique<OpObserverRegistry>();
    // 注冊 OpObserver
    opObserverRegistry->addObserver(stdx::make_unique<OpObserverShardingImpl>());
    opObserverRegistry->addObserver(stdx::make_unique<AuthOpObserver>());

    if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) {
        // shardServer 節點上,注冊 ShardServerOpObserver
        opObserverRegistry->addObserver(stdx::make_unique<ShardServerOpObserver>());
    } else if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
        // configServer 節點上,注冊 ConfigServerOpObserver
        opObserverRegistry->addObserver(stdx::make_unique<ConfigServerOpObserver>());
    }
    setupFreeMonitoringOpObserver(opObserverRegistry.get());

    serviceContext->setOpObserver(std::move(opObserverRegistry));

當有(you)監聽的動作發生(sheng)時,會調用(yong) ServerContext 結構(gou)中的 OpObserverRegistry 對應(ying)的方法。以 CollectionImpl::insertDocuments 插(cha)入(ru)動作為例:

getGlobalServiceContext()->getOpObserver()->onInserts(
        opCtx, ns(), uuid(), begin, end, fromMigrate);

Observer 操作的一致性

以(yi) insert 操作為例,對(dui)應的 observer 的動作需要與其保(bao)持一致。即同時提交或者回滾。

有(you)些 observer 動作是(shi)可以利用存儲引擎的(de)(de)事務原子性來保(bao)證的(de)(de),比如 oplog 的(de)(de)提交。

有些 observer 動作不會修改存儲引擎數(shu)據,只(zhi)是會修改內存狀態,比如(ru) AuthOpObserver 的權限更新動作。對于這些可以利(li)用 WiredTigerRecoveryUnit 的 Change 機制,在 WiredTigerRecoveryUnit 進行事務提交或(huo)者回滾之后,調用 Change 中傳入的 rollback 和 commit 回調函數(shu)完成相應的操作。

不過 Change 機制不和對應的事務一起保證原子性。可能在事務提交之后馬上斷電,沒有執行對應的 Change 回調函數。以 AuthOpObserver 為例,可能修改了 admin.system.users 表并記錄了 oplog,但是沒有來得及更新內存結構就宕機了。
不過(guo)這種(zhong)情況問題(ti)不大,因為節點重啟之(zhi)后(hou),會(hui)根據磁盤上最新的一致性數據重新構建內存數據。

文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0