Upgrade to Pro — share decks privately, control downloads, hide ads and more …

InfluxDB & LevelDB Inside-out

@smly
November 30, 2013
6k

InfluxDB & LevelDB Inside-out

Monitoring Casual Talks in Kyoto #5
http://www.zusaar.com/event/1377006

@smly

November 30, 2013
Tweet

Transcript

  1. は 保存のために 作られた時系列 • Y Combinator から出資を受けた スタートアップ Errplane が開発

    • モニタリング・アラート SaaS を立ち上げるため のバックエンドのデータベースとして開発 • ビジョンと機能が特徴的で注目を集めている
  2. から 操作 クエリ発行 ブラウザの Javascript インタプリタから 直接 DB 操作やクエリ発行が可能 #

    Create a database $ curl -sL -w "%{http_code}¥n" ¥ -X POST ¥ 'http://db:8086/db?u=root&p=root' ¥ -d '{"name": "test1"}‘ 201 Response code が 2xx なら成功
  3. # Get list of databases $ curl -s ¥ 'http://db:8086/dbs?u=root&p=root'

    ¥ | python -mjson.tool [ { "name": "test1" }, { "name": "dummy" } ] * NOTE: 2013-11-20 Undocumented feature Response body が JSON で得られる 結果は で得る
  4. # Add database user $ curl -sL -w "%{http_code}¥n" ¥

    –X POST ¥ ‘http://db:8086/db/test1/users?u=root&p=root’ ¥ -d ‘{“username”: “smly”, “password”: “yeah”}’ 200 # Get list of database users $ curl –s ¥ ‘http://db:8086/db/test1/users?u=root&p=root’ ¥ | python -mjson.tool [ { “username”: “smly” }, ]
  5. # Write points $ curl -sL -w "%{http_code}¥n" ¥ –X

    POST ¥ ‘http://db:8086/db/test1/series?u=smly&p=yeah’ ¥ -d ‘[{ “name”: “events”, “columns”: [“uid”, “action”, “item”, “price”], “points”: [ [“194016”, “BUY”, “watch”, 19999], [“194016”, “CLICK”, “watch”, 19999] ] },{ “name”: “error”, “columns”: [“uid”, “action”, “errorName”], “points”: [ [“194016”, “BUY”, “NullPointException”] ] }]’ 200 Database username/password Series name (like MySQL’s table) Series name
  6. # Write points $ curl -sL -w "%{http_code}¥n" –X POST

    ¥ ‘http://db:8086/db/test1/series?u=smly&p=yeah’ ¥ -d ‘[{ “name”: “events”, “columns”: [“uid”, “action”, “item”, “price”], “points”: [ [“5485”, “CLICK”, “watch”, 19999], ] }, { “name”: “events”, “columns”: [“uid”, “action”], “points”: [ [“5485”, “LEAVE”], ] }, }]’ 200 Schema-less !!
  7. point は “time” column が自動で追加される. これは指定することもできる. # Write points $

    curl -sL -w "%{http_code}¥n" –X POST ¥ ‘http://db:8086/db/test1/series?u=smly&p=yeah& time_precision=s’ -d ‘[ { “name”: “events”, “columns”: [“time”, “uid”, “action”], “points”: [ [1385390220, “5485”, “LEAVE”], ] }, }]’ 200 Need to specify the precision of the value Seconds (s) , milliseconds (m) or microseconds (u)
  8. Gist: https://gist.github.com/smly/7711109 (requires influxdb-python) • Generate & Write 1 point

    for each 10 seconds. • Totol points: 6 * 60 * 24 * 30 (30 days) $ git clone gist.github.com/7711109 $ cd 7711109 $ python write.py ...........................done
  9. で 時系列データを扱うことができる Support many useful aggregation/summarize functions!! $ python >

    from InfluxDB import InfluxDBClient > c = InfluxDBClient( ‘root’, ‘root’, ‘smly’, ‘secret’, ‘testdb’) # Get points in last hour > c.query(“”” SELECT * FROM markov “””)
  10. # Get points in recent 10 minutes > c.query(“”” SELECT

    * FROM markov WHERE time > now() – 10m “””) [{ “name”: “foo”, “columns”: [ “time”, “sequence_number”, “value” ], “points”: [ [1385399228, 369291, 100], [1385399218, 369292, 100.677049], ... ] }] now() と時間リテラルで 直近の 10 分のデータを指定 The `time` and `sequence_number` Columns are special built-in columns.
  11. # Get mean value grouped by 5 minutes > c.query(“””

    SELECT MEAN(value) FROM markov GROUP BY time(5m) WHERE time > now() – 1h “””) [{ “name”: “foo”, “columns”: [ “time”, “sequence_number”, “mean” ], “points”: [ [1385399100, 1, 103.01160280567923], [1385398800, 1, 102.77647754870585], ... ] }, {…}] 5 min ごとの time で GROUP BY して value の平均を計算 他, COUNT, DISTINCT など SQL にある様々な関数を 実装している
  12. 正規表現や複数の の選択ができる Schema-less なので SQL にできない複数 series の選択も可能 (time の指定がない場合は

    last hour から選択する) SELECT * FROM events, errors; SELECT * FROM /stats¥..*/i; SELECT * FROM events WHERE state == ‘NY’ SELECT * FROM log_lines WHERE line =~ /error/i; SELECT * FROM response_times WHERE value > 500; SELECT * FROM nagios_checks WHERE status != 0;
  13. による分散協調 2013-11-30 時点の #PR 20 を読んだ感想。 まだ master には merge

    されていないので変更あるか も • “Database, series, timestamp” で hash 化して得られた RingLocation 値ごとにデータを分散させる – Timestamp で区切ると効率悪くならないか? • 同一の RingLocation 値を持つサーバーで Raft による 協調&Replication が行われる – ref: http://raftconsensus.github.io/ – Ref: https://github.com/influxdb/influxdb/pull/20
  14. Flex (Fast lexical analyzer generator) + YACC (Compiler-Compiler) + Bison

    (CFG perser generator; LALR) 1. DURATION, 2. REGEX_STRING, 3. INSENSITIVE_REGEX_STRING の字句
  15. LevelDB を wrapper した Levigo を使用 (*1) 性能に影響を与える LRUCache size

    や Bloom filter の bits size は固定値(暫定的な感じ) *1: 開発者によって “may change” であると発表されている。 “Introduction to InfluxDB by Paul Dix” http://g33ktalk.com/introduction-to-influxdb
  16. LevelDB のデータストアは 1 つだけ作成. 2種類の Key:value のペアが格納される(厳密ではない) Column / Column

    ID を管理するための key/value pair Key: “[PREFIX]~[DB]~[SERIES]~[COLUMN]”, Value: ColumnID Point / Data を管理するための key/value pair Key: [TIMESTAMP][SEQ_NUM][ColumnID], Value: Data
  17. の記録例 [{ “name”: “events”, “columns”: [“uid”, “action”, “item”, “price”], “points”:

    [ [“5485”, “CLICK”, “watch”, 19999], ] }, { “name”: “events”, “columns”: [“uid”, “action”], “points”: [ [“5485”, “LEAVE”], ] }, }] [PREFIX]~test1~events~uid: 1 [PREFIX]~test1~events~action: 2 [PREFIX]~test1~events~item: 3 [PREFIX]~test1~events~price: 4 1384951400_0000001_1: “5485” 1384951400_0000001_2: “CLICK” 1384951400_0000001_3: “watch” 1384951400_0000001_4: “19999” 1384951400_0000001_5: “5485” 1384951400_0000001_6: “LEAVE” 以下のように記録される(厳密ではない) Column/ColumnID の key:value
  18. の記録例 [{ “name”: “events”, “columns”: [“uid”, “action”, “item”, “price”], “points”:

    [ [“5485”, “CLICK”, “watch”, 19999], ] }, { “name”: “events”, “columns”: [“uid”, “action”], “points”: [ [“5485”, “LEAVE”], ] }, }] 以下のように記録される(厳密ではない) Point/Data の key:value [PREFIX]~test1~events~uid: 1 [PREFIX]~test1~events~action: 2 [PREFIX]~test1~events~item: 3 [PREFIX]~test1~events~price: 4 1384951400_0000001_1: “5485” 1384951400_0000001_2: “CLICK” 1384951400_0000001_3: “watch” 1384951400_0000001_4: “19999” 1384951400_0000001_5: “5485” 1384951400_0000001_6: “LEAVE”
  19. Point/Data に対する key:value Point は timestamp, seqNum, Columnid を key

    とする 8 bytes の Buffer (x2) を作って連結して key 作成
  20. • HTTP API と Web UI でブラウザからすぐ使える • SQL-like query

    と便利拡張が使える • statsd, collectd などと連携すればHTML, CSS, JavaScript だけで Dashboard を開発できそう (誰か Kibana っぽいもの作ってください) (ref: https://github.com/obfuscurity/tasseo)
  21. の特徴 LSM-tree を採用した write-performance optimized な database library • 高速

    • Relational data model ではなく key-value storage • Key と Value は任意のバイト列 • Key はソートされて保存される • Forward/Backward iteration をサポート Paper: ” The Log-Structured Merge Tree (LSM-Tree)” http://www.cs.umb.edu/~poneil/lsmtree.pdf
  22. の に LevelDB は C0 に LockFreeSkipList (aka ConcurrentSkipList; CSL)

    を採用している C0 C1 C2 C3 Memory Disk ?
  23. なぜ の に か? 何故これ (SkipList) をLSM-Treeで使おうと 思ったかが未だちょっと理解できていない のですが、どこかに解説はないでしょうか。 “LevelDB

    の雑感 – くまメモ” http://d.hatena.ne.jp/kumagi/20111201/1322735619 “ Contributor が LSM-tree の C0 (memtable) に Hash を使わない 理由として, (1) Sorting と (2) Concurrency を挙げている http://t1825.db-leveldb.dbtalk.us/a-question-about-leveldb-s- skip-list-t1825.html kwsk
  24. の 論文 は を想定しているが • C0 の木として B-tree like ではない

    AVL-tree などを想定している • 常にメモリ上にある木であるため, Disk page size nodes である必要がないから
  25. の の性能が良い 今は Multi-core/Multi-thread 当たり前の時代 LockFreeSkipList が脚光を浴び始める。 AVL-tree とかは深さを対数に維持するため Rebalancing

    を必要とする。 並列プログラムにおいて Rebalancing は ボトルネックや競合状態を発生させる可能性がある。 “ The Art of Multiprocessor Programming, “14. Skiplists and Balanced Search”
  26. “ の の性能が良い Good high contention performance, comparable single-thread performance.

    In the multithreaded case (12 workers), CSL tested 10x faster than a RWSpinLocked std::set for an averaged sized list (1K - 1M nodes). https://github.com/facebook/folly/blob/master/folly/ConcurrentSkipList.h folly 曰く、”マルチスレッドの場合 10 倍高速”
  27. におけるチューニング • 古い話。LevelDB 1.2 は 2011-05-16 リリース • On-disk size

    を大きくして file open を減らす • Bloom Filter を導入して Throughput 底上げ Ref: http://basho.com/leveldb-in-riak-1-2/
  28. による の効率化 探索を Bloom Filter による O(1) の操作で 省略することができる(枝刈り) C0

    C1 C2 C3 Memory Disk O(1) で探索の 必要なしと判断 O(1) で探索の 必要なしと判断
  29. による効率化 無駄足は許すが 取り零しは無い Bloom Filter は LSM-tree の枝刈りに都合が良い Bloom Filter

    の答え Key がある Key がない 本 当 の 答 え Key が あ る True Positive (正解) False Netagive = 0 (取り零しはない) Key が な い False Positive != 0 (無駄足は許容する) True Negative (正解)
  30. • InfluxDB はダッシュボード開発が容易. ブラウザから SQL-like にデータ取得できる 時系列 DB . •

    Metrics 保存時には高頻度の Insert が予想 される.LSM-tree ベースの LevelDB を 使っているのは妥当そう.