簡體   English   中英

在微服務架構中管理與 MongoDb 的關系

[英]Managing relationships with MongoDb in a Microservices architecture

我使用微服務已經有一段時間了,總是使用關系數據庫。 我正在查看 MongoDb,但我不確定如何處理涉及不同微服務的實體關系。 這是一個例子:

public class Employee implements Serializable {
   private String id;
   ...
}

public class Department implements Serializable {
    private String id;
    private String desc;
    private List<Employee> employees = new ArrayList<>();
    ...
}

這兩個實體由兩個不同的微服務管理,具有由Department實體管理的一對多關系。 到目前為止,一切都很好。

使用關系數據庫(作為一個可選關系,並且一名員工可能屬於多個部門),我會在Departments微服務中使用 map ,其中一個表包含兩個字段: employee_iddepartment_id 當客戶端調用getDepartmentWithEmployees(depId)時,此微服務將讀取表並從Employees微服務中獲取適當的員工。

但是,據我所知,在 MongoDb 數據庫中,當我存儲Department object 時,它存儲所有關聯的Employee 這不是重復信息嗎? 有沒有辦法,也許,MongoDb 不存儲有關員工的所有信息,而只存儲他們的 ID? 還是有別的答案?

我很確定這是一個非常基本的問題,但我對所有這些東西都很陌生。

提前致謝。

但是,據我所知,在 MongoDB 數據庫中,當我存儲部門 object 時,它會存儲所有相關的員工。 這不是重復信息嗎?

首先,上面的說法是不正確的。 從 MongoDB 的角度來看,作為 BSON 提供的任何內容都按原樣存儲。 如果您為員工提供部門,那么是的,它應該。 您可以在創建部門后應用部分更新...(例如使用$set運算符)。 但是,我認為您的問題的 scope 比這更廣泛。

恕我直言,為數據庫中的每個文檔/表創建納米服務不是一個好方法。 特別是當服務只負責基本的 CRUD 操作時。 您應該首先定義您的有界上下文、聚合根等... 簡而言之,在將業務需求映射到域對象之前不要嘗試設計表。 我想說的是使用 DDD 原則:)

這些是我目前發現的策略。 在設計微服務時,您還應該考慮每種策略的優缺點。 (參見底部的參考資料。)

關系型數據庫映射到 NoSQL 的一般原則

  • 1:1 關系
    • 嵌入
    • 與外鍵鏈接
  • 1:M 關系
    • 嵌入
    • 與外鍵鏈接
    • (混合)分桶策略
  • N:M 關系
    • 雙向參考
    • 單向參考

1:1 關系

可以通過兩種方式映射 1:1 關系;

  • 將關系嵌入為文檔
  • 鏈接到單獨集合中的文檔

表:

// Employee document
{
   "id": 123,
   "Name":"John Doe"
}

// Address document
{
   "City":"Ankara",
   "Street":"Genclik Street",
   "Nr":10
}

示例:嵌入 (1:1)

  • 優點:可以通過一次讀取操作來檢索地址。

{
  "id": 123,
  "Name":"John Doe",
  "Address": {
    "City":"Ankara",
    "Street":"Genclik Street",
    "Nr":10
  } 
}

示例:與外鍵鏈接 (1:1)

{
   "id": 763541685,  // link this
   "Name":"John Doe"
}

帶文件密鑰的地址;

{
   "employee_id": 763541685,
   "City":"Ankara",
   "Street":"Genclik street",
   "Nr":10
}

1:M 關系

最初的:

// Department collection
{
  "id": 1,
  "deparment_name": "Software",
  "department_location": "Amsterdam"
}

/// Employee collection
[
    {
      "employee_id": 46515,
      "employee_name": "John Doe"
    },
    {
      "employee_id": 81584,
      "employee_name": "John Wick"
    }
]

示例:嵌入 (1:M)

警告:

  • 員工名單可能很大!
  • 在寫入繁重的系統中使用這種方法時要小心。 IO 負載會由於索引、復制等內務操作而增加。
  • 員工分頁很難!!!
{
  "id": 1,
  "deparment_name": "Software",
  "department_location": "Amsterdam",
  "employess": [
                   {
                     "employee_id": 46515,
                     "employee_name": "John Doe"
                   },
                   {
                     "employee_id": 81584,
                     "employee_name": "John Wick"
                   }
               ]
}

示例:鏈接 (1:M)

我們可以從員工文檔中鏈接 department_id。

  • 優點:更容易分頁
  • 缺點: Retrieve all employees that are belong to department X.這個查詢需要大量的讀取操作!
[
    {
      "employee_id": 46515,
      "employee_name": "John Doe",
      "department_id": 1
    },
    {
      "employee_id": 81584,
      "employee_name": "John Wick",
      "department_id": 1
    }
]

示例:分桶策略(混合 1:M)

  • 對於時間序列等情況很有用。
  • 混合 = 嵌入 + 鏈接
  • 優點:一次讀取 100 名員工,允許有效的分頁
  • 請參閱使用模式構建:桶模式

我們將員工分成多個桶,每個桶中最多有 100 名員工。

{
    "id":1,
    "Page":1,
    "Count":100,
    "Employees":[
        {
            "employee_id": 46515,
            "employee_name": "John Doe"
        },
        {
            "employee_id": 81584,
            "employee_name": "John Wick"
        }
    ]
}

N:M 關系

要選擇Two Way EmbeddingOne Way Embedding ,用戶必須確定 N 的最大尺寸和 M 的尺寸。
例如; 如果 N 是一本書最多 3 個類別,M 是一個類別中最多 5,000,000 本書,則您應該選擇 One Way Embedding。
如果 N 最大為 3,M 最大為 5,則雙向嵌入可能會很好地工作。 架構基礎

示例:雙向參考 (N:M)

在雙向嵌入中,我們將在作者文檔的 book 字段下包含 Book 外鍵。

作者合集

[
    {
       "id":1,
       "Name":"John Doe",
       "Books":[ 1, 2 ]
    },{
       "id":2,
       "Name": "John Wick",
       "Books": [ 2 ]
    }
]

藏書:

[
    {
       "id": 1,
       "title": "Brave New World",
       "authors": [ 1 ]
    },{
       "id":2,
       "title": "Dune",
       "authors": [ 1, 2 ]
    }
]

示例:單向參考 (N:M)

示例書籍和類別:案例是幾本書屬於幾個類別,但幾個類別可以有很多書。

  • 優點:優化讀取性能
  • 選擇在書中嵌入對類別的所有引用的原因是因為類別中的書籍比書籍中的類別多得多。

類別

[
  {
    "id": 1,
    "category_name": "Brave New World"
  },
  {
    "id": 2,
    "category_name": "Dune"
  }
]

具有Categories外鍵的Book文檔示例

[
    {
      "id": 1,
      "title": "Brave New World",
      "categories": [ 1, 2 ],
      "authors": [ 1 ] 
    },
    {
      "id": 2,
      "title": "Dune",
      "categories": [ 1],
      "authors": [ 1, 2 ] 
    }
]

參考

  1. 案例研究:一種將關系數據庫映射到 mongodb 的算法
  2. 小MongoDB Schema設計書
  3. MongoDB 架構設計的 6 條經驗法則

暫無
暫無

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

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