資料服務化在京東的實踐

帶你聊技術發表於2023-01-30


導讀 本次分享的主題為資料服務化在京東的實踐,主要包含三個模組:資料服務化的緣起、成長、如何將系統做得更好。

分享嘉賓|艾佳 京東 架構師

編輯整理|李龍傑 酷狗音樂

出品社群|DataFun



01
緣起:資料服務化從 0 到 1

1. 緣起

京東資料智慧部負責維護資料資產和對外提供資料服務,很多業務方要求我們儘快地提供開放的資料 API 供其使用,但開發一個 API 的平均週期在兩週左右,遇到 618 大促時還要提供 80 個介面。在這樣的情況下,資料開發工程師提出訴求,是否能只貼 SQL 就可以生成開放資料的 API 介面,同時又能保證介面的效能、支援傳入動態的 SQL 引數。基於該訴求而開發了一套解決方案的框架:EZD 框架。

資料服務化在京東的實踐

上圖為解決方案的示意圖,這是相對傳統固定的 API 開發模式。最下面的JavaScript 和 Java 是 API 的消費方,上面為 API 的提供方,右邊是所有 API 需要用到的資料來源。將資料來源透過 JDBC 從儲存系統中讀取出來,然後透過 HTTP 協議或者 RPC 協議開放給業務方使用。基於此套框架,資料開發工程師只需要填寫 SQL 後點選發布,系統就會根據 SQL 的內容,透過熱部署的方式生成 API 介面,達到一鍵釋出的敏捷交付目標。
2. 介面效能

資料服務化在京東的實踐

平臺第一個版本的效能存在一些瓶頸,如上圖最上面一行為資料庫查詢 API 的各個環節耗時。系統需要先去查詢 SQL 的定義,如果 SQL 是存放在資料庫裡,那麼每一個請求進來時,系統都要先去定址找到 SQL 後再去資料庫裡查詢,這樣的效率並不高。後來把 SQL 都快取到各個節點組成一張記憶體路由表來去查詢 API 的定義,查詢的過程就變得非常地快。後面連線池更換成效能更加高的 Hikari 連線池。最後經過一系列的調優,平臺的耗時佔比從最佳化前的 97% 下降到最佳化後的 1%。
3. 介面的靈活性

資料服務化在京東的實踐

好多 API 希望能傳入引數,比如查詢某條 SQL 時傳入部門的 ID,再比如使用 IN 關鍵字時能否傳入一個集合。這些又怎麼來處理呢?如上圖右小角所示,透過使用冒號的語法將 API 傳入的引數注入到 SQL 語句中。

資料服務化在京東的實踐

一些查詢條件是動態變化的,比如 WHERE 關鍵詞後邊到底是使用哪個條件?A、B、C 3 個條件構成的排列組合非常多,從而導致介面的數量較多,能否使用某種方式減少介面的數量?系統使用 SQL 與 FreeMarker 模板結合的方式來解決上述難題,從而減少 API 的數量,比如上圖最左邊使用 IF 模組判斷,只有 IF 語句為 true 時系統才會使用其內部巢狀的 AND 語句。基於這種方法,所有的查詢條件都可以是動態,同時它還支援 Switch Case、遍歷集合等操作。透過這種形式,可以將原來的 80 個介面減少到 5 個介面。

02

扛鼎:資料服務化 – 從 1 到 10
資料服務化在京東的實踐
京東 618 大促期間對外公佈的成交額、熱門品類、公關媒體的資料,各平臺的實時銷量,PV、UV、優惠券的發放情況都需要有看板去支撐,看板上特別多的指標資料都是透過上述提到的資料 API 展示出來的。
系統是如何在短期內迅速地支援這麼多的指標呢?比如京東的年貨節,需要在兩週內完成幾百個指標的開發。另外,一些響應比較慢的儲存,能不能一鍵新增快取?如何充分利用存量的 API?介面之間會形成一個特別複雜的請求鏈路,怎麼來除錯這個複雜的鏈路呢?一些業務方有自己的 elasticsearch、Redis、HBase,這些儲存怎麼去開放這個 API 呢?

資料服務化在京東的實踐

1. NoSQL 儲存生成 API
我們使用 elasticsearch-sql 元件執行 SQL 查詢 ES 儲存,該元件支援原生 painless 的 Script。對於 Redis 我們會讓這個使用者直接填好需要讀寫的 KV(系統支援新增通用的字首),系統返回 list、map 等資料格式。對於 Hbase,使用者填寫需要查詢的列簇和列,系統支援 get 和 scan 方式。
2. 一鍵新增快取
作為通用的資料服務平臺,目標是希望做到新增快取的機制與業務解耦。即無論是什麼樣的業務,進行一鍵新增快取的操作時,資料開發工程師只需要填寫 SQL,系統都會自動地增加快取。基於這些考慮,我們設計了兩種快取的機制,一種是被動快取,一種是主動快取。

資料服務化在京東的實踐

被動快取的更新是由使用者來觸發的,或者說是介面請求時觸發的。當系統收到一個請求時,如果快取的條目沒有擊中,那麼就會去建立快取條目,它的優點是傳入的引數是可以動態變化的。比如有三個請求進來,分別傳入了引數 A、引數 AB、引數 ABC,那麼這三個不同的引數組合會分別生成不同的快取條目。被動快取的缺點是 QPS 有毛刺,因為當條目不存在時,第一次請求介面時需要查詢資料庫。
為了解決被動快取的毛刺問題,我們提出了主動快取的機制,將快取更新的邏輯託管給平臺,由平臺定時地去更新快取。另外,針對傳入引數動態變化的情況,資料開發工程師只需要提前填好快取的引數,當平臺定時更新快取時就會取這些引數去載入資料。主動快取的優點是不會出現快取失效的情況,所有的請求都會命中快取,所以它的 QPS 是沒有毛刺的,缺點是需要提前填好入參的排列組合。
平臺不支援快取全量的資料,快取儲存的不應該是全量資料,而是高熱的資料。如果是業務方的需求是想要使用記憶體資料庫提高查詢效率,那麼我們建議他們使用專門的記憶體資料庫。
3. 服務編排
一些特別複雜的需求,需要大量的 API 來透過編排、組合,甚至中間的進行二次加工,然後加上一些條件判斷來形成一個複雜 API。如何來完成這樣的挑戰呢?比如在 618 大促遇到如下挑戰,618 活動是從 17 號晚上 8 點鐘開始到 19 號 0 時,這 28 小時內的不同時間段的統計邏輯是不一樣的,使用的介面也是不一樣的。我們希望把這些不同的統計邏輯都封裝到 API 裡,遮蔽掉這些複雜的業務邏輯。

資料服務化在京東的實踐

如上圖左側是一個線上執行的編排圖,整個編排鏈路中存在好多節點和分支,透過條件判斷選擇分支,除錯的時候輸入引數便可以直接看到介面請求的執行的鏈路(圖中綠色的點),一目瞭然且方便排查問題。系統的編排的底層邏輯是一個工作流引擎,它與審批工作流不一樣,它是自動流,無需人工介入。內部的好多指標都是透過這種形式來迅速的搭建 API。
03
靜思:資料服務治理
資料服務化在京東的實踐
早期的服務簡單,直接使用單體應用提供服務,後面隨著業務越來複雜,會將服務拆分成多個層級和模組,從而導致系統的複雜性急劇上升,如何對資料服務進行有效治理呢?
拋開業務和技術,治理無非是包含人員、政策、流程等因素,透過這些因素的組合,使組織達到一個期望的行為。上圖左下角展示的環狀圖就是一個流程,其中包含了政策的建立、管控、治理、宣講、執行。比如交通治理,駕駛員為客體,執法部門制定交通規則,交警執法進行約束,從而使整個流程正常運轉。

資料服務化在京東的實踐

資料服務由提供資料的生產方、使用資料的消費方以及治理方組成。服務市場將資料服務分層,由最底層的訂單、商品、使用者實體提供服務,中間存在實體互動的過程,比如交易、廣告投放,最上面是具體的應用場景,比如分析、交易、營銷。
經過治理方的規則貫宣,服務查重,服務分級,服務評價,質量控制,釋出卡點等一系列前置操作後,才能將服務提交到服務市場中。透過生產方、消費方、治理方互動的形式來完成資料服務治理的過程。
04
問答環節
Q1:資料服務的靈活性非常地高,但這種靈活性是否會帶來安全或者效能等的衝擊挑戰?
A1:平臺包含 MySQL、ClickHouse 等資料來源,每個資料來源都有所有者或者負責人,資料來源的負責人要對自己資料來源的安全性進行把關。由負責人將資料來源授權給某個 API 的分組,只有被授權的分組才能使用該資料來源。對於系統效能這個問題,平臺的負載僅僅佔到 1%,對於 API 而言,其最大的效能瓶頸在於資料庫,效能優劣完全取決於資料庫的效能以及 SQL 語句,針對這個情況我們引導使用者直接與資料庫團隊進行溝通協調、壓力測試,透過這樣的協作模式來保證服務的質量和穩定性。另外,系統擁有分散式限流的能力,在請求量超過系統能承受的最大負載時進行快速熔斷,從而保護系統。
Q2:寫了一個 MySQL 資料來源的 API,能否可以把資料來源更換成ClickHouse 或者其他的 SQL 資料來源?
A2:如果 SQL 語句能夠在新的資料來源上執行,那麼是可以的。如果 SQL語句中存在某些特定關鍵詞或者函式只能在原有資料庫引擎上執行,那麼就不能直接將資料來源修改成其它資料庫。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024922/viewspace-2933257/,如需轉載,請註明出處,否則將追究法律責任。

相關文章