Druid SQL 和 Security 在美團點評的實踐

SQL 美團網 JSON 算法 程序員 機器不學習 2019-06-17
導讀:長久以來,對 SQL 和權限的支持一直是 Druid 的軟肋。雖然社區早在 0.9 和 0.12 版本就分別添加了對 SQL 和 Security 的支持,但根據我們瞭解,考慮到功能的成熟度和穩定性,真正把 SQL 和 Security 用起來的用戶是比較少的。本次分享將介紹社區 SQL 和 Security 方案的原理,以及美團點評在落地這兩個功能的過程中所遇到的問題、做出的改進、和最終取得的效果。下面開始今天的分享:

我今天的分享內容包括四部分。首先,和大家介紹一下美團對 Druid 的使用現狀,以及我們在構建 Druid 平臺的過程中遇到的挑戰。第二部分,介紹 Druid SQL 的基本原理和使用方式,以及我們在使用 Druid SQL 的過程中遇到的問題和做的一些改進。第三部分,介紹 Druid 在數據安全上提供的支持,以及我們結合自身業務需求在 Druid Security 上的實踐經驗。最後,對今天的分享內容做一個總結。

Druid SQL 和 Security 在美團點評的實踐


一、Druid 在美團的現狀和挑戰

1.1 Druid 應用現狀

美團從 16 年開始使用 Druid,集群版本從 0.8 發展到現在的 0.12 版本。線上有兩個 Druid 集群, 總共大概有 70 多個數據節點。

數據規模上,目前有 500 多張表,100TB 的存儲,最大的表每天從 Kafka 攝入的消息量在百億級別。查詢方面,每天的查詢量有 1700 多萬次,這裡包括了一些程序定時發起的查詢,比如風控場景中定時觸發的多維查詢。性能方面,不同的應用場景會有不同的要求,但整體上 TP99 響應時間在一秒內的表佔了 80%,這和我們對 Druid 的定位——秒級實時 OLAP 引擎是一致的。

Druid SQL 和 Security 在美團點評的實踐


1.2 Druid 平臺化挑戰

把 Druid 作為一個服務提供給業務使用的過程中,我們主要遇到了易用性、安全性、穩定性三方面的挑戰。

易用性:業務會關心 Druid 的學習和使用成本有多高,是否能很快接入。大家知道,Druid 本身對數據寫入和查詢只提供了基於 JSON 的 API 接口,你需要去學習接口的使用方法,瞭解各種字段的含義,使用成本是很高的。這是我們希望通過平臺化去解決的問題。

安全性:數據是很多業務的核心資產之一,業務非常關心 Druid 服務能否保障他們的數據安全。Druid 較早的版本對安全的支持較弱,因此這一塊也是我們去年重點建設的部分。

穩定性:一方面需要解決開源系統落地過程中出現的各種穩定性問題,另一方面,如何在查詢邏輯不可控的情況下,在一個多租戶的環境中定位和解決問題,也是很大的挑戰。

Druid SQL 和 Security 在美團點評的實踐


二、Druid SQL 的應用和改進

在 Druid SQL 出現之前,Druid 查詢通過基於 JSON 的 DSL 來表達(下圖)。這種查詢語言首先學習成本很高,用戶需要知道 Druid 提供了哪些 queryType,每種 queryType 需要傳哪些參數,如何選擇合適的 queryType 等。其次是使用成本高,應用需要實現 JSON 請求的生成邏輯和響應 JSON 的解析邏輯。

Druid SQL 和 Security 在美團點評的實踐


通過 Druid SQL,你可以將上面的複雜 JSON 寫成下面的標準 SQL。SQL 帶來的便利是顯而易見的,一方面對於程序員和數據分析師沒有額外的學習成本,另一方面可以使用類似 JDBC 的標準接口,大大降低了門檻。

Druid SQL 和 Security 在美團點評的實踐


2.1 Druid SQL 簡介

下面我簡單地介紹一下 Druid SQL。

Druid SQL 和 Security 在美團點評的實踐


首先,Druid SQL 是 0.10 版本新增的一個核心模塊,由 Druid 社區提供持續的支持和優化,因此不管是穩定性還是完善性,都會比其他給 Druid 添加 SQL 方言的項目更好。

從原理上看,Druid SQL 主要實現了從 SQL 到原生 JSON 查詢語言的翻譯層。由於只是做了一層語言的翻譯,好處是 Druid SQL 對集群的穩定性和性能不會有很大影響,缺點是受限於原生 JSON 查詢的能力,Druid SQL 只實現了 SQL 功能的一個子集。

調用方式上,Druid SQL 提供了 HTTP 和 JDBC 兩種方式來滿足不同應用的需求。最後表達力上,Druid SQL 幾乎能表達所有 JSON 查詢能實現的邏輯,並且它能自動幫你選擇最合適的 queryType。

下面是三個 Druid SQL 的例子。

Druid SQL 和 Security 在美團點評的實踐


第一個例子是近似 TopN 查詢。對於根據某個指標分析單個維度 TopN 值的需求,原生的 JSON 查詢提供了一種近似 TopN 算法的實現。Druid SQL 能夠識別出這種模式,生成對應的近似 TopN 查詢。

第二個例子是半連接。我們知道 Druid 是不支持靈活 JOIN 的,但業務經常會有這樣的需求,就是以第一個查詢的結果作為第二個查詢的過濾條件,用 SQL 表達的話就是 in subquery,或者半連接。Druid SQL 對這種場景做了特殊支持,用戶不需要在應用層發起多個查詢,而是寫成 in subquery 的形式就行了。Druid SQL 會先執行子查詢,將結果物化成外層查詢過濾條件,然後再執行外層的查詢。

最後是一個嵌套 GroupBy 的例子。Druid SQL 能夠識別出這種多層的 GroupBy 結構,生成對應的原生嵌套 GroupBy JSON 。

2.2 Druid SQL 架構

Druid SQL 和 Security 在美團點評的實踐


下面介紹 Druid SQL 的整體架構。

Druid SQL 是在查詢代理節點 Broker 中實現的功能,主要包含 Server 和 SQL Layer 兩個模塊。

Server 模塊負責接收和解析請求,包括 HTTP 和 JDBC 兩類 。對於普通的 HTTP 請求,新增相應的 REST Endpoint 即可。對於 JDBC,Druid 複用了 Avatica 項目的 JDBC Driver 和 RPC 定義,因此只需要實現 Avatica 的 SPI 就行了。由於 Avatica 的 RPC 也是基於 HTTP 的,因此兩者可以使用同一個 Jetty Server。

SQL Layer 負責將 SQL 翻譯成原生的 JSON 查詢,是基於 Calcite 項目實現的。Calcite 是一個通用的 SQL 優化器框架,能夠將標準 SQL 解析、分析、優化成具體的執行計劃,在大數據領域得到了廣泛的使用。圖中淺綠色的組件是 Calcite 提供的,淺藍色的組件是 Druid 實現的,主要包括三個。

首先,DruidSchema 組件為 Calcite 提供查詢解析和驗證需要的元數據,例如集群中包含哪些表,每張表各個字段的名稱和類型等信息。RulesSet 組件定義了優化器使用的轉換規則。由於 Druid SQL 只做語言翻譯,因此這裡都是一些邏輯優化規則(例如投影消除、常量摺疊等),不包含物理優化。通過 RulesSet,Calcite 會將邏輯計劃轉成 DruidRel 節點,DruidRel 包含了查詢的所有信息。最後,QueryMaker 組件會嘗試將 DruidRel 轉成一個或多個原生 JSON 查詢,這些 JSON 查詢最終提交到 Druid 的 QueryExecution 模塊執行。

2.3 API 選擇: HTTP or JDBC

Druid SQL 提供了 HTTP 和 JDBC 兩種接口,我應該用哪個?我們的經驗是,HTTP 適用於所有編程語言,Broker 無狀態,運維較簡單;缺點是客戶端處理邏輯相對較多。JDBC 對於 Java 應用更友好,但是會導致 Broker 變成有狀態節點,這點在做複雜均衡時需要格外注意。另外 JDBC 還有一些沒有解決的 BUG,如果你使用 JDBC 接口,需要額外關注。

Druid SQL 和 Security 在美團點評的實踐


2.4 改進

下面介紹我們對 Druid SQL 做的一些改進。

第一個改進是關於 Schema 推導的性能優化。我們知道 Druid 是一個 schema-less 系統,它不要求所有的數據的 schema 相同,那如何定義 Druid 表的 schema 呢?社區的實現方式是:先通過 SegmentMetadataQuery 計算每個 segment 的 schema,然後合併 segment schema 得到表的 segment,最後在 segment 發生變化時重新計算整個表的 schema。

社區的實現在我們的場景下遇到了三個問題。第一是 Broker 啟動時間過長。我們一個集群有 60 萬個 segment,測試發現光計算這些 segment 的 schema 就需要半小時。這會導致 Broker 啟動後,需要等半個小時才能提供服務。第二個問題是 Broker 需要在內存中緩存所有 Segment 的元數據,導致常駐內存增加,另外 schema 刷新會帶來很大的 GC 壓力。第三個問題是,社區方案提交的元數據查詢量級與 Broker 和 Segment 個數的乘積成正比的,因此擴展性不好。

Druid SQL 和 Security 在美團點評的實踐


針對這個問題,我們分析業務需求和用法後發現:首先 schema 變更是一個相對低頻的操作,也就是說大部分 segment 的 schema 是相同的,不需要去重複計算。另外,絕大數情況業務都只需要用最新的 schema 來查詢。因此,我們的解決方案是,只使用最近一段時間,而不是所有的 segment 來推導 schema。改造後,broker 計算 schema 的時間從半小時降低到了 20 秒,GC 壓力也顯著降低了。

Druid SQL 和 Security 在美團點評的實踐


第二個優化是關於日誌和監控。請求日誌和監控指標是我們在運維過程中重度依賴的兩個工具,比如慢查詢的定位、SLA 指標的計算、流量回放測試等都依賴日誌和監控。但是 0.12 版本的 SQL 既沒有請求日誌,也沒有監控指標,這是在上線前必須要解決的問題。我們的目標有兩個:首先能記錄所有 SQL 請求的基本信息,例如請求時間、用戶、SQL 內容,耗時等;其次能將 SQL 請求和原生的 JSON 查詢關聯起來。因為執行層面的指標都是 JSON 查詢粒度的,我們需要找到 JSON 查詢對應的原始 SQL 查詢。

Druid SQL 和 Security 在美團點評的實踐


我們的解決方案已經合併到 0.14 版本。首先,我們會給每個 SQL 請求分配唯一的 sqlQueryId。然後我們擴展了 RequestLogger 接口,添加了輸出 SQL 日誌的方法。下圖是一個例子,對於每個 SQL 請求,除了輸出 SQL 內容外,也會輸出它的 sqlQueryId,可以用來與客戶端的日誌做關聯。還會輸出 SQL 對應的每個 JSON 查詢的 queryId,可以用來和 JSON 查詢做關聯分析。

Druid SQL 和 Security 在美團點評的實踐


第三個改進雖然比較小,但是對服務的穩定性很重要。我們知道,JSON 查詢要求用戶指定查詢的時間範圍,Druid 會利用這個範圍去做分區裁剪,這對提高性能非常重要。但是 Druid SQL 並沒有這方面的限制。用戶寫 SQL 經常會忘記加時間範圍的限定,從而導致全表掃描,佔用大量的集群資源,是一個很大的風險。所以我們添加了對 where 條件的檢查,如果用戶沒有指定時間戳字段的過濾條件,查詢會直接報錯。

Druid SQL 和 Security 在美團點評的實踐


三、Druid Security 的實踐經驗

首先介紹我們在數據安全上面臨的問題。當時使用的是 0.10 版本,這個版本在數據安全上沒有任何的支持,所有的 API 都沒有訪問控制,任何人都能訪問甚至刪除所有的數據,這對業務的數據安全來說是一個非常大的隱患。

我們希望實現的目標有五點:所有 API 都經過認證、實現 DB 粒度的權限控制、所有數據訪問都有審計日誌、業務能平滑升級到安全集群、對代碼的改動侵入性小。

為了實現這些目標,我們首先調研了 Druid 在後續版本中新增的安全功能。

Druid SQL 和 Security 在美團點評的實踐


3.1 Druid Security 功能和原理

0.11 版本支持了端到端的傳輸層加密(TLS),能夠實現客戶端到集群,以及集群各個節點之間的傳輸層安全。0.12 版本引入了可擴展的認證和鑑權框架,並且基於這個框架,提供了 BA 和 Kerberos 等認證方式,以及一個基於角色的鑑權模塊。

Druid SQL 和 Security 在美團點評的實踐


下面這張圖介紹認證鑑權框架的原理和配置。

Druid SQL 和 Security 在美團點評的實踐


Druid SQL 和 Security 在美團點評的實踐


3.2 Druid Security 社區方案缺點

社區方案能滿足我們大部分的需求,但還存在一些問題。

第一個問題是我們發現瀏覽器對 BA 認證的支持很差。因此對於 Web 控制檯,我們希望走統一的 SSO 認證。

第二個問題是為了支持業務平滑過渡到安全集群,上線初期必須兼容非認證的請求,當時我們使用的 0.12 版本沒有該功能。

第三個問題是社區基於角色的鑑權模塊只提供了底層的管理 API,用戶直接使用這些 API 非常不方便。

最後一個問題是社區還不支持審計日誌。

Druid SQL 和 Security 在美團點評的實踐


針對這些問題,我們做了三個主要的改進。

3.3 改進

改進一:基於 DB 的訪問控制

首先,為了簡化權限的管理,我們引入了 DB 的概念,並實現了 DB 粒度的訪問控制。業務通過 DB 的讀寫賬號訪問 DB 中的表。

Druid SQL 和 Security 在美團點評的實踐


改進二:自動管理權限 DB

通過任務接入平臺維護 DB 和 DataSource 的映射關係,並在 DB 和 DataSource 發生變化時,調用鑑權模塊接口更新權限 DB。

Druid SQL 和 Security 在美團點評的實踐


改進三:支持 SSO 認證和非認證訪問

自定義認證鏈條,通過 SSO 認證 Filter 實現 Web 控制檯的 SSO 認證,通過非安全訪問 Filter 兜底,兼容非認證的請求。

Druid SQL 和 Security 在美團點評的實踐


注意事項

  1. 使用 0.13 以上版本 (或者 cherrypick 高版本的 bugfix)
  2. 上線流程
  • 啟用 basic-security 功能,用 allowAll 兜底
  • 初始化權限 DB,創建匿名用戶並授權
  • 將 allowAll 替換為 anonymous
  • 逐步回收匿名用戶的權限
  1. 上線順序:coordinator->overlord->broker->historical->middleManager

四、總結

4.1 關於 SQL

  1. 如果還在用原生的 JSON 查詢語言,強烈建議試一試
  2. 社區在不斷改進 SQL 模塊,建議使用最新版本
  3. Druid SQL 本質上是一個語言翻譯層
  • 對查詢性能和穩定性沒有太大影響
  • 受限於 Druid 本身的查詢處理能力,支持的 SQL 功能有限
  1. 要留意的坑
  • 大集群的 schema 推導效率
  • Broker 需要等 schema 初始化後再提供服務(#6742)

4.2 關於 Security

  1. Druid 包含一下 Security 特性,建議升級到最新版本使用
  • 傳輸層加密
  • 認證鑑權框架
  • BA 和 Kerberos 認證
  • RBAC 鑑權
  1. 認證鑑權框架足夠靈活,可根據自身需求擴展
  2. 經歷生產環境考驗,完成度和穩定性足夠好
  3. 上線前應充分考慮兼容性和節點更新順序

作者介紹:

高大月,Apache Kylin PMC 成員,Druid Commiter,開源和數據庫技術愛好者,有多年的 SQL 引擎和大數據系統開發經驗。目前在美團點評負責 OLAP 引擎的內核開發、平臺化建設、業務落地等工作。

本文來自 高大月 在 DataFun 社區的演講,由 DataFun 編輯整理。

相關推薦

推薦中...