1. 前に書く
私の公式アカウントの記事を読んでいる学生さんは、私がこれまで「爪家庭のリファクタリング」ともいえるリファクタリングを数多く行ってきたことをご存知かと思いますが、今回のリファクタリンググラフデータベースOrientDBはNebula Graph(https://www.nebula)です。 -graph.io/) は、私がこれまでに行ったリファクタリングの中で最も難しいと言えるので、この記事ではグラフ データベース リファクタリングへの道について説明します。
2. 困難はどこにありますか
1. 歴史的負担が大きい オリジナルの OrientDB システムは 2016 年に開発されましたが、ロジックは非常に複雑で、歴史的背景はまったく不明です。
2. 事業内容が分からない 一時的にビッグデータのニーズを受けているのですが、これまでこの事業に参加したことがなく全く分かりません。
3. テクノロジースタックを知りません。グラフデータベースに触れるのはこれが初めてです (チームの誰もそのことを知りません)。これまで OrientDB と Nebula に触ったことがありませんでした。古いシステムのコードのほとんどは Scala 言語で書かれており、システムで使用されている Hbase、Spark、Kafka も私たちには比較的なじみがありません。
4. 時間が迫っています
要約すると、私はビジネスを理解していないし、テクノロジースタックにも精通していません。
ヒント: ビジネスとテクノロジーのスタックに慣れていないときに、リファクタリングをどのように行うかという質問について誰もが考えます。
3. 技術的解決策
復興技術計画についてご紹介します
1. 背景
Orion のグラフ データベース OrientDB にはパフォーマンスのボトルネックと単一点の問題があるため、Nebula にアップグレードする必要があります。
古いシステムで使用されていた技術スタックは柔軟なスケーリングをサポートできず、監視および警報機能も完璧ではありません。
2.調査項目
注: 私たちはビジネスに詳しくないので、何を調べましたか?
1) 外部インターフェイスの並べ替え: インターフェイス名、インターフェイスの目的、要求量 (QPS)、平均消費時間、呼び出し元 (サービスと IP) を含む、システムのすべての外部インターフェイスを並べ替えます。
2)、旧システムのコアプロセスを整理します。旧システムの構造図を出力し、重要なインターフェースのフローチャートを出力します(約10)。
3) 環境の分類: 変換する必要がある関連プロジェクトは何か、アプリケーションのデプロイメント、Mysql、Redis、Hbase クラスター IP、および現在のオンライン デプロイメント ブランチの分類
4) トリガーシナリオ: インターフェースがどのようにトリガーされるか。ビジネス使用シナリオから始まり、各インターフェースは少なくとも 1 つのシナリオでカバーされます。これは、後の機能検証に便利です。
5) 変換計画: 実現可能性の分析、各インターフェースの変換方法 (OrientDB ステートメントから Nebula クエリステートメント)、イメージの変換方法 (書き込みプロセス)
6)、新しいシステム設計スキーム: 出力仕分け構造図、コアフローチャート
3. プロジェクトの目標
グラフ データベース データ ソース OrientDB の Nebula への変換を完了し、旧システムの統合テクノロジー スタックを Java に再構築し、サービス レベルの拡張をサポートしました。
4. 全体計画
私たちはより抜本的な解決策を採用しました。
1. 通話インターフェースの入り口から始めて、基盤となる古いシステムを直接書き換え、影響範囲を制御可能
2. 一度限り、後のメンテナンスに便利
3. Java テクノロジー スタックを統合し、監視とメンテナンスを容易にする会社の統合サービス フレームワークにアクセスします。
4. 基本的なグラフ データベースのアプリケーション境界が明確になり、後続の上位層アプリケーションがグラフ データベースにアクセスしやすくなります。
※こちらは研究段階で描いたものですが、業務に関わるものなので掲載は省略させていただきます。
5. グレースケールスキーム
** 1) グレースケール スキーム**
書き込みリクエスト: 同期二重書き込みを使用する
読み取りリクエスト: トラフィックに応じて小規模から大規模に移行し、スムーズに移行
** 2) グレースケール計画**
ステージ1 | ステージ2 | ステージ3 | ステージ4 | ステージ5 | ステージ6 | ステージ7 |
0% | 1パーセント | 1% | 10% | 20% | 50% | 100% |
同期二重書き込み、トラフィック再生サンプリング比較、100% パス、2 日間の推定グレースケール | グレースケール 2 日 | グレースケール 2 日 | 5 日間グレースケール、この段階では圧力テストが必要です | グレースケール 2 日 | グレースケール 2 日 | - |
注記:
1. 中央スイッチ制御を設定し、問題が発生した場合はいつでも切り替えて、数秒で回復します。
2. 読み取りインターフェイスを省略しても影響はありません。変更されたインターフェイスのみが影響を受けます。
3. パラメータのハッシュ値をキーとして使用して、同じパラメータに対する複数のリクエストの結果が一貫しており、abs(key) % 1000 < X (0< X < 1000、X は動的構成) を満たすことを確認します。ヒットしたグレースケール。
余談: 実際、リファクタリングで最も重要なことはグレースケール ソリューションです。これについては前の記事でも述べました。実際のトラフィックは非同期で比較されます。比較が完全に完了した後、ボリュームが増加します。このデータ比較段階は、予想通りでした(実際には 2 週間かかり、多くの隠れた問題が見つかりました)。
6. データ比較スキーム
1) ミスのグレースケール処理は次のとおりです。
まず古いシステムを呼び出し、サンプリングがヒットしたかどうかに応じて (サンプリング率設定 0% ~ 100%)、ヒットしたサンプリングは MQ を送信し、次に新しいシステムで MQ を消費し、新しいシステム インターフェイスを要求して比較します。 json を使用した古いシステム インターフェイスによって返されたデータ 不一致 エンタープライズ WeChat 通知を送信し、データの不一致をリアルタイムで認識し、問題を発見して解決します。
逆に!!
7. データ移行計画
1)、フルボリューム (履歴データ): スクリプトは完全に移行されていますが、オンライン期間中に不整合があり、MQ からほぼ 3 日間データが消費されます。
2) インクリメント: 同期二重書き込み (書き込みインターフェイスが少ない、書き込み要求の QPS が高くない)
8. 変換のケース - サブグラフクエリを例に挙げます
1) 変身前
@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;
}
2) 変身後
グレースケールモジュールインターフェースを定義する
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 と一致し、基になるグラフ データベースは Nebula をクエリするように変更されます。
@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名
主な項目と時間がかかるものは以下のとおりです。
スキーム設計段階 | 開発段階 | テスト段階 | グレースケール |
1. 工程の仕分け 2. フローチャートの作成と構造図の整理 3. スキームの設計 |
1. 新サービスプロジェクト構築、Nebula オペレーションクラス ORM フレームワークパッケージ 2. インターフェース変換 (10 以上のインターフェース変換) 3. MQ 消費変換 4. データ比較ツール開発 (エンタープライズマイクロ通知を含む) 5. データ移行スクリプト開発 6. インターフェース共同デバッグ 7、コード グループ内の CR |
1. 機能テスト 2. データ比較 3. 100% トラフィックの旧システム回帰テスト 4. 100% トラフィックの新システム回帰テスト 5. 本番データの移行 |
1. 7 段階のグレースケールに分割され、スムーズな移行 2. 生産データのリアルタイム比較 3. 完璧な監視および警報設備 (これはストレステスト前に完了し、指標は計画ストレステスト中に観察されます) 4. ストレステスト(10%流圧テスト) 5. データバックアップ・リカバリ訓練(星雲スナップショットバックアップ使用)、容量拡張訓練 |
1週間 | 3週間 | 2週間かかった |
10. 必要なリソース
Nebula マシン 3 台、構成: 8 コア 64G、2T SSD ハードディスク
6 つの Docker サービス、構成: 2 コア 4G
4. リストラ給付金
チームによる 2 か月の懸命な作業を経て、グレースケール段階が完了し、次のようなメリットがあります。
1. Nebula 自体は分散拡張をサポートし、新しいシステム サービスは柔軟なスケーリングをサポートし、全体的なパフォーマンス レベルの拡張をサポートします。
2. 耐圧テストの結果から判断すると、インターフェイスのパフォーマンスは大幅に向上しており、サポート要求は予想をはるかに上回っています。
3. 会社に接続すると、統合された監視とアラームが得られ、後のメンテナンスが容易になります。
V. まとめ
このリファクタリングは、今回一緒にリファクタリングを行った小規模パートナー、ビッグデータとリスク管理の学生のサポート、そして Nebula コミュニティ (https://discuss.nebula-graph.com. cn/) に会って、いくつか質問をして、すぐに答えました。
WeChat 公開アカウント「アーキテクチャについて語る」に注目し、オリジナルの技術記事を随時共有してください。