時間序列數據庫武鬥大會之 KairosDB 篇

【編者按】作者劉斌是OneAPM後端研發工程師,擁有10多年編程經驗,參與過大型金融、通信以及Android手機操作系的開發,熟悉Linux及後臺開發技術。曾參與翻譯過《第一本Docker書》、《GitHub入門與實踐》、《Web應用安全權威指南》、《WEB+DB PRESS》、《Software Design》等書籍,也是Docker入門與實踐課程主講人。本文所闡述的「時間序列數據庫」,系筆者所負責產品 Cloud Insight對性能指標進行聚合、分組、過濾過程中的梳理和總結。

在前面《時序列數據庫武鬥大會之 TSDB 名錄 Part 1》和《時序列數據庫武鬥大會之TSDB名錄 Part 2》兩篇文章中,我們介紹了一些常見的 TSDB,而本文會詳細介紹KairosDB。

按照官方的說明,KairosDB 是一個 “Fast Time Series Database on Cassandra”,即基於 Cassandra 的高速時序列數據庫。

特點

1.數據採集

數據可以通過多種協議寫入 KairosDB,比如 Telnet 的按行寫入,HTTP API,Graphite 以及批處理導入。此外,還可以使用或者自己編寫插件。

2.存儲

KairosDB 採用了 Cassandra 作爲數據存儲方式,Cassandra 也是一個比較流行的NoSQL數據庫,很多開源軟件基於此數據庫。

3.Rest API

KairosDB 提供了 REST API,已完成對 metric 名稱,tag 等的查詢,當然,也少不了存儲和查詢數據點(data points)。

4.自定義數據類型(Custom Data)

KairosDB 支持存儲和聚合自定義數據類型。默認情況下 KairosDB 支持 long、double 和字符串的 value,這比 OpenTSDB 要豐富一些。

5.分組和聚合

作爲數據分析系統,分組和聚合則是必不可少的功能。 KairosDB的聚合(也就是down samples)功能,支持的標準函數有 min、max、sum、count、mean、histogram、gaps 等,而且都非常實用。

比如 percentile,可以計算一個指標值大概的百分比位置,非常適合存儲類似“你打敗了xx%的人”這種需求場景。

6.支持工具

KairosDB 提供了進行數據導入導出的命令行工具。根據官方文檔的說明,在一臺分配了 2Gig 內存的 SSD Cassandra 上,1 秒鐘能導入 13 萬條數據。

7.插件機制

KairosDB 也提供多種基於 Guice 的插件機制來進行擴展(data point 監聽器,數據存儲,協議處理等。)

KairosDB 是從 OpenTSDB fork 過來的,因此最初它是支持 HBase 的,不過現在 HBase 已經不能完全支持 KairosDB 所需的特性,將來會取消對 HBase 的支持。

入門 KairosDB

1.安裝 KairosDB

這裏我們以當前最新的1.1.1版本爲例進行說明。首先,需要確保你的JAVA_HOME已經設置好了,且Java版本高於1.6。

$ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home

然後需要到 GitHub 上去下載安裝包。我用的是 OS X 系統,因此我選擇了kairosdb-1.1.1-1.tar.gz (注意:點擊這個鏈接即可下載)。

解壓後可以看看它的配置文件conf/kairosdb.properties,有一些東西適合 OpenTSDB 一樣的,比如 4242 端口。

KairosDB 集成了 jetty,你可以通過 jetty 訪問 WEB UI,而且還支持添加 SSL 支持,這樣安全性上比 OpenTSDB 高了一個層級。

配置文件中還能對 Cassandra 進行設置,比如服務器地址、keyspace 等。不過默認的話 KairosDB 使用 H2 作爲數據存儲,這樣在開發環境下我們就不必配置Cassandra 了。這裏我們也以 H2 爲例來初步認識一下 KairosDB,這也是 KairosDB 的默認配置。

所以在這個例子裏,我們不必修改配置文件,直接啓動 KairosDB 即可:

$ bin/kairosdb.sh run
# 或者
$ bin/kairosdb.sh start

其中run參數會以前臺運行的方式啓動 KairosDB,而start則以後臺進程的方式啓動 KairosDB。

停止 KairosDB 只需要運行bin/kairosdb.sh stop就可以了。

寫入數據

和 OpenTSDB 一樣,KairosDB 也支持基於 telnet 和 HTTP API 的方式寫入數據。

1.Telnet

Telnet 的方式數據格式很簡單:

put <metric_name> <time-stamp> <value> <tag> <tag>... \n 

這裏我們就不做演示了。

2.HTTP API

只需要發送JSON數據到[http://localhost:8080/api/v1/datapoints就可以了。這是我們寫入測試數據的方法:

$ curl -v -H "Content-type: application/json" -X POST  http://localhost:8080/api/v1/datapoints -d '
[{
    "name": "cpu.load.1",
    "timestamp": 1453109876000,
    "type": "double",
    "value": 0.32,
    "tags":{"host":"test-1"}
},
{
    "name": "cpu.load.1",
    "timestamp": 1453109876000,
    "type": "double",
    "value": 0.21,
    "tags":{"host":"test-2"}
}]
'  
* Connected to localhost (::1) port 8080 (#0)
> POST /api/v1/datapoints HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
> Content-type: application/json
> Content-Length: 262
> 
* upload completely sent off: 262 out of 262 bytes
< HTTP/1.1 204 No Content  
< Access-Control-Allow-Origin: *  
< Pragma: no-cache  
< Cache-Control: no-cache  
< Expires: 0  
< Content-Type: application/json; charset=UTF-8  
< Server: Jetty(8.1.16.v20140903)  
<  
* Connection #0 to host localhost left intact

從服務器返回結果我們可以看到,HTTP 204 狀態碼,也是 KairosDB 成功寫入數據的結果。

查詢數據

同樣 KairosDB 提供了查詢用 API:

$ curl -H "Content-type: application/json" -X POST  http://localhost:8080/api/v1/datapoints/query -d '
{
  "metrics": [
    {
      "tags": {},
      "name": "cpu.load.1",
      "group_by": [
        {
          "name": JSON"tag",
          "tags": [
            "host"
          ]
        }
      ],
      "aggregators": [
        {
          "name": "sum",
          "align_sampling": true,
          "sampling": {
            "value": "1",
            "unit": "minutes"
          }
        }
      ]
    }
  ],
  "cache_time": 0,
  "start_absolute": 1453046400000,
  "end_absolute": 1453132800000,
  "time_zone": "Asia/Chongqing"
}' | jq .

注意上面命令最後的 jq,這是用來對 JSON 數據進行格式化的工具。最終結果可能像下面一樣:

{
  "queries": [
    {
      "sample_size": 2,
      "results": [
        {
          "name": "cpu.load.1",
          "group_by": [
            {
              "name": "tag",
              "tags": [
                "host"
              ],
              "group": {
                "host": "test-1"
              }
            },
            {
              "name": "type",
              "type": "number"
            }
          ],
          "tags": {
            "host": [
              "test-1"
            ]
          },
          "values": [
            [
              1453109876000,
              0.32
            ]
          ]
        },
        {
          "name": "cpu.load.1",
          "group_by": [
            {
              "name": "tag",
              "tags": [
                "host"
              ],
              "group": {
                "host": "test-2"
              }
            },
            {
              "name": "type",
              "type": "number"
            }
          ],
          "tags": {
            "host": [
              "test-2"
            ]
          },
          "values": [
            [
              1453109876000,
              0.21
            ]
          ]
        }
      ]
    }
  ]
}

WEB UI

KairosDB 自帶了一個 Web 界面,你可以通過 http://localhost:8080 訪問。不過這個 UI 主要是以開發爲目的的,可以看到查詢的 JSON 文本,方便調試,比較直觀。默認的 UI 使用了 Flot 來畫圖,如果你願意,也可以使用 Highcharts 替換。

Library

KairosDB 目前有一個單獨的 Java Client,在官網還有一些其他語言的客戶端,比如 Python、PHP 等。

由於是 Java 客戶端,所以還是很容易上手的。比如寫入數據:

MetricBuilder builder = MetricBuilder.getInstance();  
builder.addMetric("metric1")  
        .addTag("host", "server1")
        .addTag("customer", "Acme")
        .addDataPoint(System.currentTimeMillis(), 10)
        .addDataPoint(System.currentTimeMillis(), 30L);
HttpClient client = new HttpClient("http://localhost:8080");  
Response response = client.pushMetrics(builder);  
client.shutdown();  

讀取數據:

QueryBuilder builder = QueryBuilder.getInstance();  
builder.setStart(2, TimeUnit.MONTHS)  
       .setEnd(1, TimeUnit.MONTHS)
       .addMetric("metric1")
       .addAggregator(AggregatorFactory.createAverageAggregator(5, TimeUnit.MINUTES));
HttpClient client = new HttpClient("http://localhost:8080");  
QueryResponse response = client.query(builder);  
client.shutdown();  

這應該會非常方便,開發起來比 OpenTSDB 要快不少了。

其他API

KairosDB 竟然支持 metric 刪除功能,這個功能會有多少人需要呢?

列出 metric 名、tag 列表、列出 tag 值,說不定有人會喜歡,比如在輸入框自動提示燈功能,可能需要這些元數據。

1.列出指標名

這裏除了cpu.load.1是我們自己寫入的 metric,其餘的都是 KairosDB 自己的指標數據。

$ curl http://localhost:8080/api/v1/metricnames | jq .

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   501    0   501    0     0  45058      0 --:--:-- --:--:-- --:--:-- 50100  
{
  "results": [
    "kairosdb.datastore.query_time",
    "kairosdb.protocol.telnet_request_count",
    "kairosdb.http.ingest_count",
    "kairosdb.datastore.query_row_count",
    "cpu.load.1",
    "kairosdb.protocol.http_request_count",
    "kairosdb.http.ingest_time",
    "kairosdb.jvm.thread_count",
    "kairosdb.jvm.total_memory",
    "kairosdb.jvm.max_memory",
    "kairosdb.metric_counters",
    "kairosdb.jvm.free_memory",
    "kairosdb.datastore.query_sample_size",
    "kairosdb.datastore.query_collisions",
    "kairosdb.http.query_time",
    "kairosdb.http.request_time"
  ]
}

2.列出 tag key

這個 API 能列出系統中所有的 tag key。不過遺憾的是它不支持只列出某一給定指標的所有 tag key。

$ curl http://localhost:8080/api/v1/tagnames | jq .

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    67    0    67    0     0   4188      0 --:--:-- --:--:-- --:--:--  4466  
{
  "results": [
    "method",
    "metric_name",
    "query_index",
    "request",
    "host"
  ]
}

3.列出 tag value

這個 API 能列出系統中所有的 tag value。同樣遺憾的是它也不支持只列出某一給定指標的所有 tag value。所以這兩個 API 幾乎可以說是然並無用。

$ curl http://localhost:8080/api/v1/tagvalues | jq .

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   163    0   163    0     0   5011      0 --:--:-- --:--:-- --:--:--  5093  
{
  "results": [
    "1",
    "lius-MacBook-Pro.local",
    "tagnames",
    "/datapoints/query",
    "test-1",
    "test-2",
    "metricnames",
    "query",
    "tags",
    "version",
    "datapoints",
    "putm",
    "cpu.load.1"
  ]
}

總結

KairosDB 畢竟是 OpenTSDB 的一個 fork,因此根本上的功能都差不多,而且隨着 OpenTSDB 對 Cassandra 的支持,感覺 KairosDB 相比 OpenTSDB 也沒有什麼太大的優勢。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章