re:newalhttp://blog.flect.co.jp/cloud/からさらに引っ越しています2018-06-28あなたの身近にもあるかもしれない『ダブりデータ』みなさんこんにちは。エンジニアの佐藤です。今回はIoTの話題をご紹介させていただきたいと思います。load)処理によりDWHに収めました。このシステムは運用暦約1年で、利用量は右肩上がりで上昇してきました。蓄積データの活用が企画され、数億件のデータがDWHに集積されました。多数のデバイスが毎日送信して積み上げてきたものです。コンピュータと名の付く物、何事も疑いの目で見なければなりません。筆者がまず気になったのは、「まともなデータなのか」という点です。数億レコードともなると、もはや個別確認はできません。どんなゴミが混入しているのかわかったものではありません。「まともなデータ」の基準はいろいろあると思いますが、筆者が一番重要だと思うのは、一意性です。RDBMSで言えば「テーブルのキー項目は何か」ということになります。DWHにユニーク制約はありませんから、スキーマが一意性を担保することはありません。この点から確認する必要があります。このシステムの場合、送信データにはデバイスのID、対象事象発生時のデバイス時刻、シーケンス番号が含まれています。シーケンス番号は電源OFFでリセットされますから、一意ではありませんが、デバイスのIDは重複がないことが保証されています。時刻は外部の信頼できる時計に自動補正ですから、一旦正確だと前提しましょう。デバイスID、事象発生時のデバイス時刻、ログ到着時刻の全てが重複することは、仕様上無いはずです。DWHにはBigQueryを使っていますので、以下のようにクエリしてこの点を確認してみました。一部は伏字または仮の値にしています。|+-------------------------+-----------+---------------------+-------+それ見たことか。日付が変わった直後から約1秒間の間で発生しているように見えます。念には念を入れて受信した生データも比較してみましたが、完全に重複しています。これはいわばデータの「バグ」。原因を特定せねばなりません。何と何がダブっているのか同じデータが2回DWHに登録された理由は何か?この原因追求のために役立つのが、私が「経路情報」と呼んでいる、レコードの出自に関する記録です。ETL処理の節目ごとにこの経路情報を追記していき、全てのレコードについて元ネタが特定できるように仕掛けておくのです。今回のダブりデータについて経路情報(log_file_pos)を表示すると、以下のようになりました。簡単に解説しますと、「2018-06-09/1/343159(00717206)/00」は、2018年06月09日のログファイルに記録された、受信ホスト1番が出力したログファイルの第343159番目のデータで、ファイルの第717206行目に記録されている、という意味です。(末尾の「/00」は説明を省略します。|+-------------------------+-----------+---------------------+----------------------------------+この経路情報をダブりデータで比較してみると、連続する2つの日付の、ちょうど境界あたりに分布していることがわかります。ここまでくると、ダブりの原因は、日付ごとにログファイルを分ける処理にある可能性が高いと考えるのが妥当でしょう。Logsに出力されたログを定期的にエクスポートしてS3へ保存させたものです。このエクスポート処理の設定は定時ジョブで実行しており、以下のようになっています。24時間(=86400秒)離れています。良さそうですが、この種の境界設定については、常に「inclusive(指定値を含む)」なのか「exclusive(指定値は含まない)」かを注意する必要があります。以下のURLからAPIの仕様を確認してみましょう。inclusiveです。この点については、不注意だったと言えます。原因がわかりました!と言いたいところですが、あれ?何かおかしいですよね。00:00:00.572」に分布していたのです。1ミリ秒ではなく、1秒ですね。結局AWSのこのAPI、ミリ秒指定と言っておきながら、ミリ秒部分は評価していないようです。上記のAPIリファレンスの文章に当てはめてみましょう。ログが、入ってしまっているわけです。ミリ秒単位で指定させておきながら、これはひどいよな、と思います。ExclusiveにすればOK、なのか?AWSのAPI仕様はわかりました。s3_prefix)つまり、2018-06-09のログファイルについては以下のような指定になるわけです。included.筆者は、これは危険な設定だと思います。今度はエクスポートの欠損が起こる可能性があるからです。到着したら、取りこぼされてしまいます。Logsログ取得APIの仕様によると、https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_GetLogEvents.htmlhttps://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_OutputLogEvent.htmlログの収録時刻(ingestionTime)は「ミリ秒単位の整数」となっていますので、23:59:59.9995は、23:59:59.999か、翌日00:00:00.000に丸められるでしょうから、現時点では大丈夫そうではあります。Logsがミリ秒よりさらに細かい到着時刻記録をサポートした場合、取りこぼしの心配が生じる可能性があります。(あくまで仕様上の話ですが。)筆者の結論としては、このエクスポート設定コードは、このままにしておくことにしました。データの受信記録が永久的に失われるというのは非常に恐ろしい出来事ですので、潜在的な危険はできるだけ排除したい。それなら多少の手間をかけ、後から重複を除去した方がマシ、だと思ったのです。これで終わり、ではなかった!これでダブりデータの原因は特定されました。安心して眠れそうです。以外の時間帯のダブりデータ」を探してみました。見つけてしまったのです。|+-------------------------+-----------+---------------------+---------------------------------+このダブりはこれまで特定した原因だけでは説明できません。何が起こったのか、筆者は元ログを調査しました。その結果、同時刻に同一データの到着が2回記録されていることを発見してしまいました。ここでは時刻はデバイスからのデータを受信するインスタンスのシステム時刻で、JSTで書かれている。Logsもクエリしてみましたが、上記の2行のログは、全く同時刻に到着しています。contains("4dxxxx..."))|.ingestionTime'15288142547741528814254774次はネットワーク通信ログを、と言いたいところですが、残念ながらここまでは記録していませんでした。どこかで想定外の重複動作があったのでしょうが、真実はやぶの中です。原因が特定できないので対策方針が立つわけもなく、データクレンジングで対処するしかありません。今回の場合は同一デバイス・同一時刻に発生する物理事象はひとつに決まっていますから、ダブりデータのうちひとつだけを採用すれば良いでしょう。この類の現象にどんな姿勢で臨めば良いのかここまでくると、「もう何を信じて良いやら」という気持ちになってきました。結局ログの記録、転送のそれぞれの段階で、ぴったり完璧とは行かない例外事象が起こってしまっているのです。マニュアルも厳密でなく、オーナーシップがあるわけでもないので仕様は変わる。いう状態でデータ分析をやるときは、いかなるポリシーを定めて事に取りかかればいいのでしょうか?筆者の結論は以下のようなものです。データが途中で消えるのは困るので、ダブりを許容するしかない。ダブりは、最後に洗い落とすしかない。プログラムコードのデバッグにも似た対策措置が、データに対しても必要なようです。最後までお読みいただき、ありがとうございました。v4の転移学習みなさんこんにちは。技術開発室の岡田です。〜黄金の風〜こんにちは。Cariot事業部の遠藤です。APIでWebサイトを比較するみなさんこんにちは。エンジニアの佐藤です。エンジニアの佐藤です。専門知識に合格しました月別アーカイブはてなブログをはじめよう!flect_techさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。