乾物丨DolphinDBストリームコンピューティングエンジンを使用してセンサーデータの異常検出を実現する方法

DolphinDBデータベースは、モノのインターネットでのセンサーデータの異常検出を含む、リアルタイムデータ処理用のストリームテーブルとストリームコンピューティングエンジンを提供します。組み込みの異常検出エンジン(異常検出エンジン)は、ほとんどの異常検出シナリオのニーズを満たすことができます。異常検出ロジックが複雑で特殊であり、標準化された異常検出エンジンが要件を満たせない場合、ユーザーはカスタムメッセージ処理機能を使用してそれを実装できます。


1.アプリケーション要件

監視システムは毎秒データを収集します。次の2つの異常検出要件があります。

  • 3分ごとに、センサーの温度が摂氏40度を2回超え、摂氏30度を3回超えると、システムはアラームを発します。
  • センサーネットワークが切断され、5分以内にデータがない場合、システムはアラームを発します。

上記のアラームは、異常が検出された場合にストリームデータテーブルにレコードを書き込むことを示しています。


2.デザインのアイデア

分散時系列データベースDolphinDBのストリームコンピューティングフレームワークは、現在、時系列集約エンジン断面集約エンジン異常検出エンジン、およびカスタムストリームコンピューティングエンジンをサポートしてます

  • 時系列アグリゲーター:デバイスステータスの垂直集計計算(時系列で集計)を実行したり、複数のデバイス状態を水平方向に集計してから時間に従って集計したりできます。時系列集計は、スライディングウィンドウを使用したスト​​リーミング計算をサポートします。DolphinDBは、組み込みのウ​​ィンドウ集約機能のパフォーマンスを最適化し、シングルコアCPUは、1秒あたり約100万状態のタイミング集約を完了することができます。
  • Cross Sectional Aggregator(Cross Sectional Aggregator):スナップショットエンジンの拡張機能であり、デバイスのバッチの平均温度の計算など、デバイスのステータスに対して水平方向の集計計算を実行できます。
  • 異常検出エンジン:データがユーザー定義のアラームインジケータを満たしているかどうかをリアルタイムで検出できます。異常データが見つかった場合は、リアルタイムの監視とインターネットの早期警告のニーズを満たすためにテーブルに出力されます。物事。
  • カスタムストリームコンピューティングエンジン:上記の3つのエンジンのいずれも需要を満たすことができない場合、ユーザーはDolphinDBスクリプトまたはAPI言語を使用してメッセージ処理機能をカスタマイズすることもできます。

最初の要件では、センサーの温度が3分以内に異常になるとシステムがアラームを発し、異常検出エンジンがちょうど適しています。DolphinDBスクリプトを使用して式を記述し、例外ロジックを記述します。ただし、2番目の要件は適用されません。異常検出エンジンは、デバイスのグループ化によって処理されます。計算は、新しいデータが流入するたびにトリガーされるか、固定長の移動ウィンドウで間隔を置いて集計計算が実行されます。センサーが新しいデータを生成しない場合、計算をトリガーすることはできません。解決策は、メッセージハンドラー(メッセージハンドラー)をカスタマイズして計算および検出することです。具体的な実現のアイデアは次のとおりです。Key-Valueメモリテーブルを使用して、各センサーの最新の取得時間を記録します。メッセージは、特定の時間間隔(たとえば、1秒)でメッセージ処理機能に入ります。メッセージ処理機能は、最初にKey-Valueメモリテーブルを更新し、次にこのテーブルの各デバイスによって記録された最新の収集時間が5分を超えているかどうかを確認し、超えている場合はアラームを発します。

 

3.詳細な実装手順


3.1入力および出力ストリームデータテーブルを定義します

まず、リアルタイムで収集されたセンサーデータを受信するストリーミングデータテーブルを定義し、enableTableShareAndPersistence関数を使用して、ストリーミングデータテーブルをハードディスクに共有および永続化します。cacheSizeパラメーターは、メモリーに保持されるデータの最大量を100万行に制限します。センサーデバイスには多くのインジケーターがありますが、この例には温度インジケーターのみが含まれているため、この例ではテーブル構造が簡略化されています。テーブル構造には、センサー番号deviceID、時間ts、温度の3つの列のみが含まれます。コードは次のように表示されます。

st=streamTable(1000000:0,`deviceID`ts`temperature,[INT,DATETIME,FLOAT])
enableTableShareAndPersistence(table=st,tableName=`sensor,asynWrite=false,compress=true, cacheSize=1000000)

次に、異常検出エンジンの出力用のアラーム出力ストリームデータテーブルを定義します。DolphinDBユーザーマニュアルのcreateAnomalyDetectionEngineのパラメーターの説明によると、異常エンジンには出力テーブルの形式に関する厳しい要件があります。つまり、最初の列は、検出された異常のタイムスタンプを格納するために使用される時間タイプである必要があります。 、およびこの列のデータ型は、入力テーブルの時間列と一致している必要があります。keyColumn(グループ化列)パラメーターが空でない場合、2番目の列はkeyColumnです。この例では、グループ化列はセンサー番号deviceIDです。次の2つの列は、int型とstring / symbol型であり、例外の型(メトリックの添え字)と例外の内容を記録するために使用されます。テーブルコードは次のとおりです。

share streamTable(1000:0, `time`deviceID`anomalyType`anomalyString, [DATETIME,INT,INT, SYMBOL]) as warningTable

3.2異常センサー温度警報の機能を実現するための異常検出エンジンを作成する

異常検出エンジンで、異常インデックスをsum(温度> 40)> 2 && sum(温度> 30)> 3に設定します。グループ化列(keyColumn)はセンサー番号deviceID、データウィンドウwindowSizeは180秒、計算された時間間隔ステップは30秒です。これらのパラメータの設定方法は、異常検出エンジンを参照できますコードは次のように表示されます。

engine = createAnomalyDetectionEngine(name="engine1", metrics=<[sum(temperature > 40) > 2 && sum(temperature > 30) > 3  ]>,dummyTable=sensor, outputTable=warningTable, timeColumn=`ts, keyColumn=`deviceID, windowSize = 180, step = 30)
subscribeTable(tableName="sensor", actionName="sensorAnomalyDetection", offset=0, handler= append!{engine}, msgAsTable=true)

3.3センサーオフラインアラームの機能を実現するためのカスタムメッセージ処理機能を作成する

2番目の要件は、各センサーの最新のデータ収集時間を保存して、データが5分間収集されていないかどうかを判断することです。この例では、Key-Valueメモリテーブルを使用して各デバイスの最新の状態格納し、センサー番号deviceIDを主キーとして使用します。Key-Valueテーブルでは、Key-Valueに基づく検索と更新の効率が非常に高くなっています。センサーデータを受信するときは、append!関数を使用してKey-Valueテーブルのレコードを更新します。新しいレコードの主キー値がテーブルに存在しない場合は、新しいレコードをテーブルに追加します。新しいレコードの主キー値が既存のレコードの主キー値と重複する場合、対応する主キー値はテーブルはのレコードを更新します。

異常情報をアラーム出力ストリームデータテーブルに出力する場合、前節の異常検出エンジンはすでに0を使用しているため、異常anomalyTypeのタイプは1に設定されます。例外の内容は空に設定されています。

構成関数subscribeTableのパラメーターthrottleおよびbatchSizeは、メッセージのバッチ処理のパフォーマンスを向上させるという目的を達成できます。パラメータthrottleは、ハンドラがメッセージを処理する頻度を決定します。この例では、1秒ごとに処理するように設定されています。ここで、メッセージ数がbatchSizeに達すると、間隔が切れていなくても着信メッセージが処理されるため、batchSizeを比較的大きな数に設定する必要があることに注意してください。サンプルコードは次のとおりです。ここで、センサーの数deviceNumは3と想定されています。

t=keyedTable(`deviceID,100:0,`deviceID`time,[INT,DATETIME])
deviceNum=3
insert into t values(1..deviceNum,take(now().datetime(),deviceNum))
def checkNoData (mutable keyedTable, mutable outputTable, msg) {
	keyedTable.append!(select deviceID, ts from msg)
	warning = select now().datetime(), deviceID, 1 as anomalyType, "" as anomalyString from keyedTable where time < datetimeAdd(now().datetime(), -5, "m")
	if(warning.size() > 0) outputTable.append!(warning)
}
subscribeTable(tableName="sensor", actionName="noData", offset=0,handler=checkNoData{t, warningTable}, msgAsTable=true, batchSize=1000000, throttle=1)


4.シミュレーションの書き込みと検証

3つのセンサーが1秒に1回データを収集すると仮定すると、すべてのデバイスには前の1分間のデータがあり、3番目のデバイスには1分後にデータがありません。サンプルコードは次のとおりです。

def writeData(){
	deviceNum = 3
	for (i in 0:60) {
		data = table(take(1..deviceNum, deviceNum) as deviceID, take(now().datetime(), deviceNum) as ts, rand(10..41, deviceNum) as temperature)
		sensor.append!(data)
		sleep(1000)
	}
	deviceNum = 2
	for (i in 0:600) {
		data = table(take(1..deviceNum, deviceNum) as deviceID ,take(now().datetime(), deviceNum) as ts, rand(10..45,deviceNum) as temperature)
		sensor.append!(data)
		sleep(1000)
	}	
}
submitJob("simulateData", "simulate sensor data", writeData)

実行後、警告出力テーブルwarningTableをクエリすると、結果が次のようになります。


付録

テストコード

おすすめ

転載: blog.csdn.net/qq_41996852/article/details/112799453