Y's note

MongoDBのCapped CollectionとTailable Cursorを使ったRealTimeAccess集計

[MongoDB] : MongoDBのCapped CollectionとTailable Cursorを使ったRealTimeAccess集計 Index RealTimeAccess集計 Capped Collection Tailable Cursor まとめ RealTimeAccess集計 RealTimeAccess集計をするためにMongoDBの利用を考えます。サーバーの構成は上図のようなイメージで各種ApplicationServerからFluentdでLogAggregatorにRealTimeでLogデータを転送し、LogAggregator MasterがMongoDBにFluentdで書き込んで行きます。ここで言うRealTimeAccess集計の機能要件を整理すると以下のようになります。 Access発生後、1分以内で集計結果をWebツール上で確認したい。集計区間も1分単位など。 複数条件が指定可能で、柔軟なCross集計がしたい。 RealTimeAccess集計のSystem負荷を出来る限り抑えたい。 Access発生後の直ぐに確認ということでFluentdが必要、柔軟なCross集計のために1行のAccessLogをそのままMongoDBに格納という方法を採用します。以下ではこれを実現するためのMongoDBの機能であるCapped CollectionとTailable Cursorについて説明します。 Capped Collection MongoDBにはCapped Collectionというデータ数とサイズの上限を指定できるCollectionがあります。cappedコレクション - Docs-Japanese - 10gen Wiki Capped Collectionの良いところは指定した上限サイズに達した場合は古いデータを自動的に削除してくれるところです。よってRealTimeAccess集計のような短時間のみデータが必要なケースに向いています。更に自動削除によりエンジニア泣かせとされる深夜帯の定期削除バッチたるものが不要になります。また通常のCollectionより書き込みが速くなります。速度のパフォーマンス比較は以下の通りです。50万件のInsertでCapped Collectionの方が20%ほど処理時間が短くなります。 $ mongo MongoDB shell version: 2.2.3 connecting to: test use capped_test; db.createCollection("cappedcoll", {capped:true, size:100000, max:10000}); { "ok" : 1 } db.createCollection("normalcoll"); { "

Google先生の検索結果リンクが予想以上に作り込まれていた件

[調査] : Google先生の検索結果リンクが予想以上に作り込まれていた件 Index 検索結果のリンクは単なるRedirectorでは無かった 検索結果のhttps化 httpsからhttpページへの遷移ではブラウザはRefererを送らない Google先生はRerererを送る仕組みを実装してくれた Refererが送信される処理の流れを追う httpsからhttpsページへの遷移はどうなるか Google Analyticsで検索Queryが「not provided」となる本当の理由 まとめ 検索結果のリンクは単なるRedirectorでは無かった 知らなかったのが僕だけだったら凄い恥ずかしい内容なんですが、今までGoogle先生の検索結果として表示されるリンクのURLはGoogle内部でClick集計するためのRedirector機能だと思っていました。カウントアップの集計を記録したら本来のURLに遷移させるような。当然そのClick数を集計する機能も持ち合わせているんでしょうが、もう少しユーザーにも優しくClickした遷移先のサービスの事も考えられた親切な仕組みになっていたのでここにメモを残しておきたいと思います。 検索結果のhttps化 2011年頃からGoogle先生は検索結果ページをhttps化させていますね。最初はGoogleのログインユーザーが対象だったと思うんですが、最近は全ユーザーを対象とするようになって来ています。これは検索機能にしては結構チャレンジングな事だと思います。httpと比較すると認証局との通信等を含めて処理が重たくなるし、単純に証明書のお金も掛かるし、セキュリティレベルの高い情報入力ページ以外での導入は避けられがちです。(※最近はhttpsの処理高速化としてSPDYとか技術開発も進んでいるみたいですね。SPDY - Wikipedia ) セキュリティ面を気にするユーザー視点からすると通信の暗号化という点は安心できる事だと分かりますが、大半の人は処理がさくさく動いてくれれば特にというレベルでしょうか。 httpsからhttpページへの遷移ではブラウザはRefererを送らない HTTP/1.1: Security Considerations Clients SHOULD NOT include a Referer header field in a (non-secure) HTTP request if the referring page was transferred with a secure protocol. RFCの記述にもあるようにClientはhttpsからhttpページへの遷移の場合はRefererを送らないようにと記述されています。一応各種ブラウザはこのルールを守っていてhttpsからhttpへの遷移ではRefererを送りません。Refererは遷移元を特定するための超重要なHttpHeaderです。このブラウザが「Refererを送らない」という仕様がWebサービスを公開している人にとってはとても痛い事で、Googleからの遷移かどうかが分からなくなってしまいます。 Google先生はRerererを送る仕組みを実装してくれた ブラウザが「Refererを送らない」問題を偉大なGoogle先生は解消してくれています。httpsの検索結果からhttpのページへRefererを送信しています。処理手順は以下のようになります。 検索結果のリンクはhttp://www.google.co.jp/urlのようにhttpのスキーマで定義する。 http://www.google.co.jp/urlは200OKでhtmlを返す。(302 Foundで遷移先URLを返さない) ブラウザは200OKのhtmlを取得する。取得したhtml内部のjavascriptおよびMETA http-equiv="

データ集計コマンドを極めてシステム処理と業務速度を爆速化するお話

[Linux] : データ集計コマンドを極めてシステム処理と業務速度を爆速化するお話 Index データ集計コマンド 爆速で検索したいぜ! lookを使う LC_ALL=Cを設定する データのランダムサンプリングがしたいぜ! sedを使う awkを使う sortの--random-sortを使う Script言語を使う shufを使う ランダムサンプリング速度比較 合計と平均値を集計したいぜ! 列データ取得 重複行のカウント 合計値出力 平均値出力 複数ファイルのデータ結合がしたいぜ! 共通項目での結合 同じ行数での結合 まとめ データ集計コマンド joinコマンドが便利過ぎて生きるのが辛い - Yuta.Kikuchiの日記 lookコマンドによる二分探索が速すぎて見えない - Yuta.Kikuchiの日記 今日はデータ集計を行う上で絶対に覚えておいた方が良いコマンドと知識を紹介したいと思います。これを身につければシステム処理と業務効率化に大きく繋がると思います。この記事で紹介するコマンドはlook、sort、cut、uniq、shuf、awk、sed、join、pasteで、設定知識としてLC_ALL=Cについても軽く触れたいと思います。その他perl、pythonの一行野郎についても少し書きます。下で紹介する例はとにかく一行野郎に拘って書いていますので、見づらい事は予めご了承ください。 爆速で検索したいぜ! lookを使う 検索するコマンドで誰もがgrepを使っていると思いますがドキュメント全てを検索対象としてしまうので処理速度が遅くなります。grep以外に検索するための良いコマンドとしてlookというものがあります。lookは予め検索対象のデータをsortしておく必要がありますが、2分探索が可能なので繰り返しシステムが大量データから検索する場合に有効だと思います。以下1000万行のデータに対してgrepとlookを使った時の検索時間の比較になります。使用するデータのFormatは英数字の32Byte文字列になります。 #!/usr/bin/env perl use warnings; use strict; use String::Random; open(FH, "data.txt"); for(my $i=0; $i10000000; $i++ ) { my $rand_str = String::Random-new-randregex('[A-Za-z0-9]{32}'); print FH $rand_str .

Multi-Class Classifier of Bra Size used as the feature value with vital statics

[機械学習] : Multi-Class Classifier of Bra Size used as the feature value with vital statics Multi-Class Classifier of Bra Size アダルトフィルタ実装に向けたA○女優リストの自動抽出 + α - Yuta.Kikuchiの日記 前回のA○女優リストの自動抽出の流れから今日は実験を行います。本来の目的だったアダルトフィルタ作成から話がどんどんズレて行きます。今日のお題はVital Staticsを特徴量としてBra SizeのMulti-Class問題を解きます。タイトルを英語にしたのはこの下らない実験をさも真面目な研究としてやったかのようにカモフラージュするためです。初めに断っておきますが今回の実験を振り返った結果、反省はしている、だが後悔もしている状態です。 Vital Statics - Wikipedia 一般的な話ですがVital StaticsからBra Sizeを導きだすのは難しいとされています。( BraSize = TopBust - UnderBust。UnderBust ≠ Waist ) 確かに個人のVital Staticsからは算出は難しいのかもしれませんが、集団データから傾向の推定はできるのでは無いかというのが今回の実験のテーマです。下のようにBraの項目が欠損している方もいるのでそこをMachine Learningの力で補完して行きます。 Name:瑠川リナ Bust:81 Waist:57 Hip:83 Bra:D65 Name:☆LUNA☆ Bust:83 Waist:57 Hip:82 Bra:D-65 Name:RUMIKA Bust:82 Waist:60 Hip:85 Bra:C Name:麗花 Bust:88 Waist:58 Hip:87 Bra:E Name:Reo.

アダルトフィルタ実装に向けたA○女優リストの自動抽出 + α

[programming] : アダルトフィルタ実装に向けたA○女優リストの自動抽出 + α アダルトフィルタ実装に向けて エロデータサイエンティストの@yutakikucです。 今日はSystemで使うアダルトフィルタの辞書データ作成を目的としていた事が、予想外な方向に突き進んでしまった事をお話します。 アダルトフィルタの良くある活用例としてはユーザーが投稿する内容に卑猥単語が含まれている場合は登録を弾くことです。アダルトフィルタの辞書データを作成/運用することは実は結構大変だったりします。なぜならば人目で1語ずつ卑猥か否かを判断したり、自分で判断できない際どい単語はGoogle先生に聞きながらだったり..当然新語が増えればアダルトフィルタ辞書の運用コストも膨れるからです。 そこで作成/運用のコストを大幅に下げるために辞書の更新を自動化したいと考えます。例えば新しいA○女優がデビューした場合、名前をアダルトフィルタの辞書に自動登録するようなものです。今日はそれをPythonで実装し、最終的にはLTSV形式のデータで出力します。 Labeled Tab-separated Values (LTSV) サンプルコード A○女優一覧 - Wikipedia データソースはWikipediaに乗っている日本のA○女優一覧になります。上のURL以下をスクレイピングする事で名前のリストを抽出します。今回のアダルトフィルタに必要となるデータ項目は名前ですが、折角なのでVital Statistics(Three Size)、Bra Sizeもついでのついでのついでに取得します。保存するLTSVのフォーマットは以下のように定義します。 Name: Bust: Waist: Hip: Bra: 以下がスクレイピングを行うPythonコードです。更新データが直ぐに欲しい場合はCron等で定期的に実行してください。※時間が無くて10分ぐらいで書いたコードなので汚いです。 #!/usr/bin/env python # -*- coding: utf-8 -*- # アダルトフィルタのデータ抽出 import sys,re,urllib,urllib2 f = open( 'av.txt', 'w' ) opener = urllib2.build_opener() ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.51.22 (KHTML, like Gecko) Version/5.

【進撃の巨大データ】RealTimeLog集計を目的としたRedisの活用

[Redis] : 【進撃の巨大データ】RealTimeLog集計を目的としたRedisの活用 Log集計の設計を再考 【進撃の巨大データ】Log集計用DBとシステム構成の美しい設計を考える - Yuta.Kikuchiの日記 人生を前向きに楽しむことを心に誓った@yutakikucです。最近はこのブログで【進撃の巨大データ】というタイトルで何回かBigDataに関する記事を書いています。前回はLog集計用DBとシステム構成の美しい設計を考えるという題でInnoDB、InfiniDBを使ったLog集計のmerit/demerit、SystemPerformanceについて記述しました。それから時間をおいて再考し、InnoDBを使う場合のメリット/デメリットと注意事項が不足している事に気づいたのでここで追記します。更に集計の緊急度に合わせて使用するDBを変えます。リアルタイムではRedis、定期処理ではMysqlを使って集計することを試してみたいと思います。 Log集計方法のmerit/demerit 4のRedisを使うは今回新しく追加した項目です。 No Method merit demerit 1 InnoDBを使う。格納時点でデータを集計。 1行中の集計用カラムを都度Update。 特定のデータ集計を1行で管理可能。 行数が膨らまない。 集計SQLのPerformanceを出す事ができる。 書き込み口が複数あると行ロックが心配なので、 サーバ構成を工夫しなければ行けない。 格納時にデータを集約してしまうので、 シンプルで特定の集計しかできない。 【追記】データの書き込みや集計に失敗するとリカバリが大変。 2 InnoDBを使う。格納時点でデータを1行ずつ書き込む。 集計時にSQLで行数をSUMる。 行ロックの心配が無くなる。 【追記】処理ミスの影響範囲が行レベルに収まる。 行数が膨大になる。 集計用SQLも重くなるし、GROUP BYにも限界がある。 行数が膨らまないように 定期的に古いデータは削除するなどの処理が必要。 3 InfiniDBを使う。格納時点でデータを1行ずつ書き込む。

【進撃の巨大データ】Log集計用DBとシステム構成の美しい設計を考える

[Mysql] : 【進撃の巨大データ】Log集計用DBとシステム構成の美しい設計を考える Log集計用DB設計 考える問題 Document無しのAgile開発をガチで推奨したい@yutakikucです。【進撃の巨大データ】の第2回目として巨大アクセスLog集計用DBの設計について勉強した内容についてメモしたいと思います。DB周りはそこまで詳しく無いので詳しい皆様からの突っ込み大歓迎でございます。また図々しいですが知恵をください(笑)。 今日の主目的は下の2要件を叶えるためのDB設計を考える事です。特に問題になるのがRealTimeの話でTableにLogDataを書き込む処理と集計のSQLをどのように組み立てるか、それ以外にもSystemPerformanceとArchitectureにも関わってきます。 リアルタイムで大量データを集計したい 定期処理で大量データを集計したい 使うもの Fluentd : Fluentd: Open Source Log Management Mysql Innodb : MySQL :: MySQL 5.1 リファレンスマニュアル :: 13.5.3 InnoDB 設定 Mysql Infinidb InfiniDB – the high performance, column oriented analytic database Fluentdを使ってNginxLogをMysqlにリアルタイムで格納する - Yuta.Kikuchiの日記 FluentdはRealTimeでLogをLog収集用のサーバに転送とDBへの書き込み、Mysql InnodbはLogデータを格納するDBです。以前これらを用いてNginxのLogをリアルタイムで格納することを試したのでよければ上のリンクを参照してください。なぜMysqlか?という質問が出そうですが、安定と実績を買います。Mongodbのようなスキーマレスの方が後から柔軟に集計が可能という話もでてきそうですが、必要なデータ項目だけを抽出してディスク容量を抑えることと集計の高速化を目指します。そんなことしないで最初からTresureData使えよって話もありそうですが、自前で作りたいというプライドのためです(笑) Mysqlの種類も行指向のInnoDBと集計処理に向いているとされる列指向のinfinidbの両方を使ってみます。 リアルタイム大量データの格納をどうするか? リアルタイム大量データ格納の方法を決める上で重要ポイントとなのがMysqlのrowをどのように使うかです。取り得る方法とそれぞれのメリット/デメリットを考えて下にまとめました。もしMongodbのようなKVSを使ったLog集計でもKeyとValueをどのように使うかという同じ問題になると思います。 No Method merit demerit 1 InnoDBを使う。格納時点でデータを集計。

【進撃の巨大データ】自作ApacheModuleとRedisでWebBrowserを一つ残らずUnique管理する

[Apache] : 【進撃の巨大データ】自作ApacheModuleとRedisでWebBrowserを一つ残らずUnique管理する BrowserID管理の必要性 BehaviorTargeting調査レポート - Yuta.Kikuchiの日記 進撃の巨人とADTechnologyの面白さを最近の楽しみとしている@yutakikucです。BigDataという言葉が大変流行っていますが、巨大な力を持つ大量のユーザーアクセスとそれから生まれるログ、その処理と分析に追われるエンジニア/データサイエンティストはまさに進撃の巨人と人間の闘いのようです(笑)この記事のタイトルは進撃の巨人でエレンが言った「巨人を一匹残らず駆逐してやる」を文字っています。今日はそんな巨大データを扱うADTechnology分野のUserTrackingに欠かせないBrowser識別子とUnique管理について触れたいと思います。ADTechの面白さを少し話しておくと検索やKVS等の最新技術だけでなく機械学習や統計のアカデミック領域の知識も必要で、本当に毎日が勉強の連続です。目的はユーザーに最適な広告を表示してCTRを稼ぐ事でゲームをやってる時のワクワク、宝の山を探すロマン?!みたいなものを感じたりするんですよね。そんな最適な広告表示のためにCookieの中にBrowserIDという識別子を設定して、AccessLogからBrowserIDを取得してRedisに行動履歴を書き込むための技術を紹介します。実行環境はCentOSの6.3です。 Apacheの標準Moduleを使ってBrowserIDを生成 mod_usertrack mod_usertrack.c ApacheModuleを自作する前に標準Moduleのmod_usertrackを使ってみます。mod_usertrackはCookieを指定した名前と有効期限で設定することができます。利用するためにはhttpd.confでLoadModule usertrack_module modules/mod_usertrack.soを有効にし、CookieTracking on CookieExpires "1 years" CookieName BrowserIDの3行を追記します。これで有効期間が1年間のBrowserIDを自動で発行します。追記が終わったらapacheのrestartを実行します。それでは設定したhostにアクセスしてみます。今回はlocalhostになります。curl --dump-headerでアクセスしたファイルのCookieを見てみるとBrowserID=::1.1372482316740936; という名前のCookieで識別子が振られている事がわかります。1.1372482745843590という値ですが、アクセス元IPとUnixTime情報の組み合わせのようです。しかしmod_usertrackのBrowserID生成には以下の問題があります。IPAddressとUnixTimeではパラメータのバリエーションが少ないので、以下の二つの条件が重なると問題が発生します。この問題を解決するために次章では自作のApache ModuleでBrowserIDを管理します。 アクセス元が携帯キャリアGWの場合同一になるケースが存在する。 UnixTimeに同一時間にRequestが来てしまうケースがある。 $ sudo vim /etc/httpd/conf/httpd.conf LoadModule usertrack_module modules/mod_usertrack.so CookieTracking on CookieExpires "1 years" CookieName BrowserID $ sudo /usr/sbin/httpd -k restart $ curl --dump-header - "http://localhost/cookie_test" HTTP/1.1 200 OK Date: Sat, 29 Jun 2013 05:12:25 GMT Server: Apache/2.2.15 (CentOS) Set-Cookie: BrowserID=::1.

誰もが一度は陥る日付処理。各種プログラミング言語におけるDateTime型/TimeStamp型の変換方法のまとめ

[programming] : 誰もが一度は陥る日付処理。各種プログラミング言語におけるDateTime型/TimeStamp型の変換方法のまとめ 日付型の変換処理 Date/Timestamp変換のまとめ - Yuta.Kikuchiの日記 10言語のプログラミング言語に対してそこそこの知識を保有している@yutakikucです。いろんなプログラミング言語を使用していると文法を覚えるのは大変ですよね。PHP書いている途中からJavaScriptの文法を誤って書き始めたり... それぞれの言語の文法の違いを事細かく覚える事は無理に近いです。今日はそんな各種言語仕様の記述で難解なDateTime/TimeStampについて紹介したいと思います。扱うのはWeb系のメジャープログラミング言語のSQL/C++/Java/JavaScript/Perl/PHP/Python/Rubyになります。Mysqlからデータを取り出した後や、WebAPIから取得したデータを表示用の日付フォーマットに変換する事があると思うのでそこで利用できる知識になるかと思います。そもそもDateTime型/TimeStamp型って何だよっていう人もいるかと思うので簡単にまとめると以下のようになります。※ここでのTimeStampはUnixTimeを表現しています。 型 意味 例 DateTime YYYY-MM-DD HH:mm:SSで表現する時刻Format 2013-05-31 20:33:20 TimeStamp 1970/1/1からの秒数で上限は2037年まで 1370000000 変換重要処理早見表 言語 DateTime取得 TimeStamp取得 DateTime変換 = TimeStamp TimeStamp = DateTime変換 Mysql NOW() UNIX_TIMESTAMP() UNIX_TIMESTAMP() FROM_UNIXTIME() C++ time_t型, struct tm構造体, strftime(datetime, N, "

MongoDBのAggregation Framework/MapReduceを使ってより賢く集計を行うためのまとめ

[MongoDB] : MongoDBのAggregation Framework/MapReduceを使ってより賢く集計を行うためのまとめ Mogodb集計 MongoDBの集計機能が便利過ぎて泣けてくるお話し - Yuta.Kikuchiの日記 1月程前にMongoDBを使った集計機能の紹介をさせていただいた@yutakikucです。内容は全く大した事無かったのですが、タイトルで誘導を引っ張って200近いbookmarkを集める事ができました笑。みなさんの参考にしていただけたこと、大変嬉しく思います。今日はMongoDBの集計をもう一歩踏み込んだ内容を紹介して行きたいと思います。題材としてはAggregation FrameworkとMapReduceについてです。因に今回試してみたMongoDB-Versionは2.2.3です。Versionによって挙動が変わると思うので注意してください。 $ mongo --version MongoDB shell version: 2.2.3 Aggregation Framework Aggregation ― MongoDB Manual 2.4.4 SQL to Aggregation Framework Mapping Chart ― MongoDB Manual 2.4.4 Aggregation FrameworkはRDBMSのSQLに備わっている便利機能をMongoDBに付与したFrameworkという説明が分かりやすいと思います。MongodbのVerson2.2以降に備わった機能です。以下はMongodbのAggregation OperatorとRDBMSのSQLの対応表になります。一つずつのOperatorはFilterに近いイメージで、Chainをしてパイプライン処理とすることができます。最終的にはChainした結果を取得します。 MongoDB Aggregation Operator SQL Term,Function,Concepts $match WHERE $group GROUP BY $project SELECT $sort ORDER BY $limit LIMIT $sum SUM(),COUNT() $avg AVERAGE() CentOSでNginxのログをFluentdを使ってMongodbにリアルタイムで格納する - Yuta.