分析のため、機密情報をいい感じにマスクしたプロダクションDBのコピーを毎日作っている
Helpfeel Tech Hour vol.1の発表資料ですshokai.icon
こんにちは、shokaiですshokai.icon
Scrapbox.icon Scrapboxのプロダクトマネージャーをしています
実態
コンセプトを考えて設計して実装して運用して〜みたいな色々をやっています
最近
分析環境を作り始めました
今日はその話をします
毎日、MongoDBのコピーを作っている
https://gyazo.com/099c489da6edcc6572ca8d71179dfe43
タイトルや本文テキストをマスクしている
md5 文字列の長さという形式
アクセスできる人
今はビジネス系の1人だけ
将来増える
転送にかかる時間
1時間ぐらい
なぜそんな事をしているのか
サービスの利用状況を分析したい
操作ログでは扱えない領域がある
例
ページのリンクのグラフ構造
どういうサイズのページを作ってる?上と下どっちに追記するの?共同編集者の数は?調べてみました!
production DBそのものを分析したい
セキュリティポリシーを守りつつ、ビジネス系の人がDBにアクセスできるようにしたい
顧客が書いたテキストは機密情報
「読んじゃダメ」ではなく「読めない」にするべき
md5 文字数という形式でマスクする
リンクの構造や編集頻度、ページの規模などは分析できる
転送batchを速くしたい
なるべく最新のデータを反映したい
毎日production DBからコピーする
まちがえて壊しても24時間で復活するし、最高
実装
ダメだった構成
MongoDB Atlasの自動バックアップから定期的にリストア
production全体だとデータが大きすぎて、リストアに時間がかかる
mongodumpしてマスクしてmongorestore
mongoexportしてマスクしてmongoimport
どちらも、巨大なexportファイルができてつらい
3工程を順にやるので効率悪い
exportしたファイルを自力でparseしてマスク処理するの大変
最終的にこうなった
1つのプログラムで2つのDBをつなぐパイプライン
1. production DBからのread
2. 本文のマスク処理
3. 分析用DBへのwrite
これを4スレッドでやる
read/writeのI/O待ちの間に、CPUを使うマスク処理がちょうど走る
実装のポイント
mongooseではなくnode-mongodb-nativeを直接使う
mongooseはDB1からreadして、DB2にそのまま同じdocumentを書き込むような処理が書けない
_idを指定した新規documentのinsertができない為
node-mongodb-nativeでやる
code:js
for await (const page of srcDb.collection('pages').find(condition, option)) {
/* ここにfieldをマスクする処理 */
await destDb.collection('pages').insertOne(page)
}
久しぶりに使ったけど、mongooseと使用感はそれほど変わらなかったshokai.icon
安全装置が無いだけ
fieldの型情報、validator、hook機構など
いい感じに並列処理
こう書くと、規模が異なるprojectが混在していても良い感じになる
project IDの配列を作っておいて
code:js
const projectIds = (await srcDb.collection('projects').find({ plan: 'business' }, { _id: 1 }).toArray()).map(({ _id }) => _id)
project ID配列をタスクのキューとし、空になるまで4並列で処理していく
code:js
await Promise.all(Array(4).fill().map(async () => {
while (projectIds.length > 0) {
const projectId = projectIds.shift()
await transferProject({ projectId, srcDb, destDb })
}
}))
転送するfieldはallow listで指定する
deny listはダメ
fieldが増えた時に転送対象になってしまう
データの投入が終わってからindexを付ける
先にindexが付いていると
insert毎にソートが走って、CPUが詰まる
index後付けにしたら
全体の処理時間が40%高速化した
まとめ
操作ログではなく、現状のDBのデータそのものを、マーケやCSの人にも分析させたい
名前や本文などの機密情報はマスクしたい
色々やったら速くて安全なのやつができた