Sentry 監(jiān)控 - Snuba 數(shù)據(jù)中臺架構(gòu)(Data Model 簡介)
本節(jié)介紹數(shù)據(jù)在 Snuba 中的組織方式以及面向用戶的數(shù)據(jù)如何映射到底層數(shù)據(jù)庫(如: Clickhouse)。
Snuba 數(shù)據(jù)模型橫向分為邏輯模型(logical model)和物理模型(physical model)。邏輯數(shù)據(jù)模型是 Snuba 客戶端通過 Snuba 查詢語言可見的。此模型中的元素可能會也可能不會 1:1 映射到數(shù)據(jù)庫中的表。相反,物理模型將 1:1 映射到數(shù)據(jù)庫概念(如表和視圖)。
這種劃分背后的原因是,它允許 Snuba 通過邏輯數(shù)據(jù)模型公開一個穩(wěn)定的接口,并在內(nèi)部執(zhí)行復雜的映射,對不同的表(物理模型的一部分)執(zhí)行查詢,以一種對 client 透明的方式提高性能。
本節(jié)的其余部分概述了組成兩個模型的概念以及它們?nèi)绾蜗嗷ミB接。
下面描述的主要概念是數(shù)據(jù)集(dataset)、實體(entity)和存儲(storage)。
數(shù)據(jù)集
Dataset 是 Snuba 數(shù)據(jù)的命名空間。它提供了自己的 schema,并且在邏輯模型和物理模型方面都獨立于其他數(shù)據(jù)集。
數(shù)據(jù)集的示例是 discover(發(fā)現(xiàn))、outcomes(結(jié)果)、sessions(會話)。他們之間沒有任何關(guān)系。
數(shù)據(jù)集可以看作是定義其抽象數(shù)據(jù)模型及其具體數(shù)據(jù)模型的組件的容器,如下所述。
實體和實體類型
Snuba 向客戶端公開的邏輯數(shù)據(jù)模型的基本塊(fundamental block)是實體。在邏輯模型中,實體表示抽象概念(如 transaction 或 error)的實例。在實踐中,Entity 對應(yīng)于數(shù)據(jù)庫表中的一行。Entity Type 是實體的類(如 Errors 或 Transactions)。
邏輯數(shù)據(jù)模型由一組 Entity Types 及其 relationships 組成。
每個 Entity Type 都有一個 schema,該模式由具有相關(guān)抽象數(shù)據(jù)類型的字段列表定義。 Dataset 的所有 Entity Types(可以有多個)的 schema 組成了對 Snuba client 可見的邏輯數(shù)據(jù)模型,Snuba 查詢根據(jù)該模型進行驗證。不應(yīng)該暴露較低級別的概念。
Entity Types 明確包含在 Dataset 中。一個 Entity Type 不能出現(xiàn)在多個數(shù)據(jù)集中。
實體類型之間的關(guān)系
數(shù)據(jù)集中的實體類型在邏輯上是相關(guān)的。支持兩種類型的關(guān)系:
- 實體集關(guān)系(Entity Set Relationship)。這模仿了外鍵。這種關(guān)系旨在允許實體類型之間的連接。目前它只支持一對一和一對多的關(guān)系。
- 繼承關(guān)系(Inheritance Relationship)。這模仿了名義上的子類型(subtyping)。一組實體類型可以共享一個父實體類型。子類型從父類型繼承 schema。從語義上講,父實體類型必須表示其類型從其繼承的所有實體的聯(lián)合。還必須能夠查詢父實體類型。這不能僅僅是一種邏輯關(guān)系。
實體類型和一致性
Entity Type 是 Snuba 可以提供一些強大的數(shù)據(jù)一致性保證的最大單元。具體來說,可以查詢期望 Serializable Consistency(可序列化的一致性) 的實體類型。這不會擴展到跨越多個實體類型的任何查詢,在這種情況下,我們最多將具有最終的一致性。
這也會對訂閱查詢(Subscription queries)產(chǎn)生影響。這些一次只能對一種實體類型起作用,否則,它們將需要實體類型之間的一致性,而我們不支持這種一致性。
請注意!
準確地說,一致性單位(取決于 Entity Type)甚至可以更小,并且取決于數(shù)據(jù)攝取主題(data ingestion topics)的分區(qū)方式(例如 project_id),實體類型是 Snuba 允許的最大值。
存儲
Storage 表示并定義 Dataset 的物理數(shù)據(jù)模型。每個 Storage 表示在物理數(shù)據(jù)庫概念中具體化,如表或具體化視圖。因此,每個存儲都有一個由字段及其類型定義的 schema,該字段反映了 storage 映射到的 DB table/view 的物理模式,并且能夠提供生成 DDL 語句的所有詳細信息,以在數(shù)據(jù)庫上構(gòu)建表。
Storage 能夠?qū)⑸厦嬗懻摰倪壿嬆P椭械倪壿嫺拍钣成涞綌?shù)據(jù)庫的物理概念,因此每個 Storage 都需要與一個 Entity Type 相關(guān)聯(lián)。具體來說:
- 每個 Entity Type 必須由至少一個 Readable Storage(我們可以在其上運行查詢的 Storage)支持,但可以由多個 Storage(例如預聚合物化視圖pre-aggregate materialized view)支持。每個 Entity Type 的多個 Storage 旨在允許查詢優(yōu)化。
- 每個 Entity Type 必須由一個且僅一個用于攝取數(shù)據(jù)和填充數(shù)據(jù)庫表的 Writable Storage 支持。
- 每個 Storage 僅支持一種 Entity Type。
示例
本節(jié)提供了一些示例,說明 Snuba data model 如何表示一些現(xiàn)實世界模型。
這些案例研究不一定反映當前的 Sentry production model,也不一定是同一部署的一部分。它們必須被視為孤立的例子。
單一實體數(shù)據(jù)集
這看起來像 Sentry 使用的 Outcomes 數(shù)據(jù)集。這實際上并沒有反映截至 2020 年 4 月的 Outcomes。盡管設(shè)計 Outcomes 應(yīng)該朝著這個方向發(fā)展。
該 Dataset 只有一種 Entity Type,代表數(shù)據(jù)集攝取的單個 Outcome。查詢 raw Outcome 非常緩慢,所以我們有兩個 Storage。一個是反映我們攝取的數(shù)據(jù)的 Raw storage 和一個計算每小時聚合的 materialized view,查詢效率更高。Query Planner 將根據(jù)查詢是否可以在聚合數(shù)據(jù)上執(zhí)行來選擇 storage。
多個實體類型數(shù)據(jù)集
此數(shù)據(jù)集的典型示例是 Discover 數(shù)據(jù)集。
這具有三種 Entity Type。Errors、Transactions 并且它們都繼承自 Events。這些形成了邏輯數(shù)據(jù)模型,因此查詢 Events Entity Type 給出了 Transactions 和 Errors 的聯(lián)合,但它只允許查詢中存在兩者之間的公共字段。
出于性能原因,Errors Entity Type 由兩個 Storage 支持。一個是用于攝取數(shù)據(jù)的主要 Errors Storage,另一個是read only view(只讀視圖),在查詢時對 Clickhosue 的負載較少,但提供較低的一致性保證。 Transactions 只有一個 storage,并且有一個 Merge Table 來為 Events 提供服務(wù)(本質(zhì)上是兩個表聯(lián)合的視圖)。
連接實體類型
這是一個簡單的數(shù)據(jù)集示例,其中包含可以在查詢中連接在一起的多個實體類型。
GroupedMessage 和 GroupAssingee 可以是帶有 Errors 的 left join 查詢的一部分。其余部分與前面示例中討論的內(nèi)容類似。