“本文由社群使用者 @阿七從第一視角講述其團隊重構圖資料庫的過程,首發於阿七公眾號「淺談架構」”
原文出處:https://mp.weixin.qq.com/s/WIJNq-nuuAGtMjYo5rPLyg
一、寫在前面
讀過我公眾號文章的同學都知道,我做過很多次重構,可以說是“重構釘子戶”,但是這次,重構圖資料庫 OrientDB 為 NebulaGraph(https://www.nebula-graph.com.cn/),可以說是我做過最艱難的一次重構。
那這篇文章就來聊聊,圖資料庫重構之路。
二、難點在哪裡
- 歷史包袱重,原來使用 OrientDB 系統是2016年開始開發的,邏輯很複雜,歷史背景完全不清楚。
- 業務不瞭解,我們是臨時接的大資料需求,之前沒有參與過這塊業務,完全不瞭解。
- 技術棧不瞭解,圖資料庫是第一次接觸(團隊中也沒有人瞭解),OrientDB 和 NebulaGraph 之前都沒有接觸過,原來老系統大部分程式碼是 Scala 語言寫的,系統中使用的 HBase、Spark、Kafka,對於我們也比較陌生。
- 時間緊迫
總結來說: 業務不瞭解,技術棧不熟悉
tips: 大家思考一個問題,在業務和技術棧都不熟的情況下,如何做重構呢?
三、技術方案
下面介紹一下本次重構技術方案
1、遷移背景
獵戶座的圖資料庫 OrientDB 存在效能瓶頸和單點問題,需升級為 NebulaGraph。
老系統是用使用技術棧無法支援彈性伸縮,監控報警設施也不夠完善。
具體的使用痛點後續我將會寫一篇文章具體講述下,本篇就不詳細展開了。
2、調研事項
注:既然業務都不熟悉,那我們都調研了哪些東西呢?
- 對外介面梳理:梳理系統所有對外介面,包括介面名、介面用途、請求量 QPS、平均耗時,呼叫方(服務和 IP);
- 老系統核心流程梳理:輸出老系統整理架構圖,重要的介面(大概 10 個)輸出流程圖;
- 環境梳理:涉及到的需要改造的專案有哪些,應用部署、MySQL、Redis、HBase 叢集 IP,及目前線上部署分支整理;
- 觸發場景:介面都是如何觸發的,從業務使用場景出發,每個介面至少一個場景覆蓋到,方便後期功能驗證;
- 改造方案:可行性分析,針對每一個介面,如何改造(OrientDB 語句改為 NebulaGraph 查詢語句),入圖(寫流程)如何改造;
- 新系統設計方案: 輸出整理架構圖,核心流程圖。
3、專案目標
完成圖資料庫資料來源 OrientDB 改造為 NebulaGraph,重構老系統統一技術棧為 Java,支援服務水平擴充套件。
4、整體方案
我們採用了比較激進的方案:
- 從呼叫介面入口出發,直接重寫底層老系統,影響面可控;
- 一勞永逸,方便後期維護;
- 統一 Java 技術棧、接入公司統一服務框架,更利於監控及維護;
- 基礎圖資料庫應用邊界清晰,後續上層應用接入圖資料庫更簡單。
注:這裡就貼調研階段畫的圖,圖涉及業務,我這裡就不列舉了。
5、灰度方案
灰度方案
- 寫請求:採用同步雙寫
- 讀請求:按流量從小到大陸續遷移、平滑過渡
灰度計劃
階段一 | 階段二 | 階段三 | 階段四 | 階段五 | 階段六 | 階段七 |
---|---|---|---|---|---|---|
0% | 1‰ | 1% | 10% | 20% | 50% | 100% |
同步雙寫, 流量回放取樣對比,100% 透過、預計灰度 2 天 | 灰度 2 天 | 灰度 2 天 | 灰度 5 天、此階段要壓測 | 灰度 2 天 | 灰度 2 天 | - |
注:
- 配置中心開關控制,有問題隨時切換,秒級恢復。
- 讀介面遺漏無影響, 只有改到的才會影響。
- 使用引數 hash 值作為 key,確保同一引數多次請求結果一致、滿足 abs(key) % 1000 < X ( 0< X < 1000, X 為動態配置 ) 即為命中灰度。
題外話:其實重構,最重要的就是灰度方案,這個我在之前文章《淺談這些年做過的千萬級系統重構專案》也提到過。本次灰度方案設計比較完善,大家重點看階段一、在灰度放量之前,我們用線上真實的流量去非同步做資料對比,對比完全透過之後,再放量,本次對比階段比預期長了很多(實際上用了 2 周時間,發現了很多問題)。
6、資料對比方案
未命中灰度
未命中灰度流程如下:
先呼叫老系統,再根據是否命中取樣(取樣比例配置 0% ~ 100%),命中取樣會傳送 MQ,再在新系統消費 MQ,請求新系統介面,於老系統介面返回資料進行 JSON 對比。對比不一致,傳送企業微信通知,實時感知資料不一致,發現並解決問題。
反之亦然!!
7、資料遷移方案
- 全量(歷史資料):寫指令碼全量遷移,上線期間產生不一致從 MQ 消費近 3 天資料
- 增量:同步雙寫(寫的介面很少,寫請求 QPS 不高)
8、改造案例 - 以子圖查詢為例
改造前:
@Override
public MSubGraphReceive getSubGraph(MSubGraphSend subGraphSend) {
logger.info("-----start getSubGraph------(" + subGraphSend.toString() + ")");
MSubGraphReceive r = (MSubGraphReceive) akkaClient.sendMessage(subGraphSend, 30);
logger.info("-----end getSubGraph:");
return r;
}
改造後:
定義灰度模組介面
public interface IGrayService {
/**
* 是否命中灰度 配置值 0 ~ 1000 true: 命中 false:未命中
*
* @param hashCode
* @return
*/
public boolean hit(Integer hashCode);
/**
* 是否取樣 配置值 0 ~ 100
*
* @return
*/
public boolean hitSample();
/**
* 傳送請求-響應資料
* @param requestDTO
*/
public void sendReqMsg(MessageRequestDTO requestDTO);
/**
* 根據
* @param methodKeyEnum
* @return
*/
public boolean hitSample(MethodKeyEnum methodKeyEnum);
}
介面改造如下, kgpCoreService 請求到 kgp-core 新服務,介面業務邏輯和 orion-x 保持一致、底層圖資料庫改為查詢 NebulaGraph:
@Override
public MSubGraphReceive getSubGraph(MSubGraphSend subGraphSend) {
logger.info("-----start getSubGraph------(" + subGraphSend.toString() + ")");
long start = System.currentTimeMillis();
//1. 請求灰度
boolean hit = grayService.hit(HashUtils.getHashCode(subGraphSend));
MSubGraphReceive r;
if (hit) {
//2、命中灰度 走新流程
r = kgpCoreService.getSubGraph(subGraphSend); // 使用Dubbo呼叫新服務
} else {
//這裡是原來的流程 使用的akka通訊
r = (MSubGraphReceive) akkaClient.sendMessage(subGraphSend, 30);
}
long requestTime = System.currentTimeMillis() - start;
//3.取樣命中了傳送資料對比MQ
if (grayService.hitSample(MethodKeyEnum.getSubGraph_subGraphSend)) {
MessageRequestDTO requestDTO = new MessageRequestDTO.Builder()
.req(JSON.toJSONString(subGraphSend))
.res(JSON.toJSONString(r))
.requestTime(requestTime)
.methodKey(MethodKeyEnum.getSubGraph_subGraphSend)
.isGray(hit).build();
grayService.sendReqMsg(requestDTO);
}
logger.info("-----end getSubGraph: {} ms", requestTime);
return r;
}
9、專案排期計劃
投入人力: 開發 4 人,測試 1 人
主要事項及耗時如下:
10、所需資源
略,這裡不展開講述。
四、重構收益
經過團隊 2 個月奮鬥,目前已完成灰度階段,收益如下
- NebulaGraph 本身支援分散式擴充套件,新系統服務支援彈性伸縮,整體支援效能水平擴充套件;
- 從壓測結果看,介面效能提升很明顯,可支撐請求遠超預期;
- 接入公司統一監控、告警,更利於後期維護。
五、總結
本次重構順利完成,感謝本次一起重構的小夥伴,以及大資料、風控同學支援,同時也感謝 NebulaGraph社群(https://discuss.nebula-graph.com.cn/),我們遇到一些問題提問,也很快幫忙解答。
謝謝你讀完本文 (///▽///)
如果你想嚐鮮圖資料庫 NebulaGraph,記得去 GitHub 下載、使用、(^з^)-☆ star 它 -> GitHub;和其他的 NebulaGraph 使用者一起交流圖資料庫技術和應用技能,留下「你的名片」一起玩耍呀~
2023 年 NebulaGraph 技術社群年度徵文活動正在進行中,來這裡領取華為 Meta 60 Pro、Switch 遊戲機、小米掃地機器人等等禮品喲~ 活動連結:https://discuss.nebula-graph.com.cn/t/topic/13970