データベース
OpenTSDB
概要
OpenTSDBは、Apache HBaseをベースとして構築された分散・スケーラブルな時系列データベースです。StumbleUponによって2010年に開発され、数十億のデータポイントを効率的に保存・処理できる能力を持ちます。IoTデバイス、サーバー監視、アプリケーションメトリクスなど、大量の時系列データを扱うシステムに最適化されています。
詳細
主要特徴
- 無制限のスケーラビリティ: HBaseの分散アーキテクチャを活用し、ノードを追加するだけで線形にスケール
- 高いカーディナリティ: タグ(キー・バリューペア)による柔軟なデータ識別が可能
- 生データの保持: デフォルトで集約せずに元のデータを保存
- 強力なクエリ機能: HTTP APIやコマンドライン経由での複雑な集約・フィルタリング
- プラグインシステム: 認証、検索、リアルタイム配信などのカスタム拡張に対応
- コマンドラインツール: データインポート、クエリ、UID管理など包括的なツール群
アーキテクチャ
OpenTSDBは3つの主要コンポーネントで構成されています:
- tCollector: 各サーバーに配置され、メトリクスデータを定期的に収集
- TSD (Time Series Daemon): データを受信してHBaseに保存、クエリ処理を担当
- HBase: バックエンドストレージシステムとして動作
データモデル
時系列データは以下の要素で識別されます:
- メトリクス名: 測定対象(例:cpu.usage、memory.free)
- タグ: key=valueペアによる識別子(例:host=web01、region=us-east)
- タイムスタンプ: データポイントの時刻
- 値: 測定値
効率的な保存のため、文字列名は一意のバイナリID(UID)にマッピングされます。
メリット・デメリット
メリット
- 卓越したスケーラビリティ: 1秒間に数百万の書き込みを処理可能
- HBaseの成熟したエコシステム: 豊富な運用ノウハウとツール
- 柔軟なタグシステム: 高いカーディナリティに対応
- 長期保存: データ保持期間に制限なし
- オープンソース: 無料で利用可能、アクティブなコミュニティ
- RESTful API: 簡単な統合とクエリが可能
- プラグイン対応: カスタマイズ性が高い
デメリット
- 複雑なセットアップ: HBaseクラスタの構築・運用が必要
- 高いハードウェア要件: 最低4GB RAM推奨、本格運用には更に多くのリソースが必要
- 学習コストの高さ: HBaseとOpenTSDBの両方の知識が必要
- リアルタイム性の制約: バッチ指向のため、極めて低遅延が必要な用途には不向き
- SQL未対応: 独自のクエリ構文を学習する必要
- InfluxDBやTimescaleDBと比較してモダンさに欠ける: 新しい時系列DBに比べて設計が古い
主要リンク
書き方の例
インストール・セットアップ
前提条件
# Java 8以上が必要
java -version
# HBase 0.94以上が必要
# ZooKeeperクラスタも事前に構築
Dockerを使用した簡単セットアップ
# OpenTSDBコンテナを起動
docker run -d \
--name opentsdb \
-p 4242:4242 \
petergrace/opentsdb-docker
# Webインターフェースにアクセス
# http://localhost:4242
設定ファイル(/etc/opentsdb/opentsdb.conf)
# HBaseへの接続設定
tsd.storage.hbase.zk_quorum = localhost:2181
tsd.storage.hbase.zk_basedir = /hbase
# ポート設定
tsd.network.port = 4242
# 新しいメトリクスの自動作成
tsd.core.auto_create_metrics = true
# メタデータキャッシュの有効化
tsd.core.meta.enable_realtime_ts = true
基本操作(データ挿入・クエリ)
データ挿入(HTTP API)
# 単一データポイントの挿入
curl -X POST http://localhost:4242/api/put \
-H "Content-Type: application/json" \
-d '{
"metric": "cpu.usage",
"timestamp": 1609459200,
"value": 45.2,
"tags": {
"host": "web01",
"region": "us-east"
}
}'
# 複数データポイントの一括挿入
curl -X POST http://localhost:4242/api/put \
-H "Content-Type: application/json" \
-d '[
{
"metric": "memory.usage",
"timestamp": 1609459200,
"value": 78.5,
"tags": {"host": "web01", "type": "physical"}
},
{
"metric": "memory.usage",
"timestamp": 1609459260,
"value": 79.1,
"tags": {"host": "web01", "type": "physical"}
}
]'
Telnetインターフェース経由での挿入
# Telnetクライアントでの接続
telnet localhost 4242
# データフォーマット: put <metric> <timestamp> <value> <tag1=value1> [<tag2=value2>...]
put cpu.usage 1609459200 45.2 host=web01 region=us-east
put memory.free 1609459260 2048 host=web01 type=available
データクエリ
# 基本的なクエリ
curl "http://localhost:4242/api/query?start=1h-ago&m=avg:cpu.usage{host=web01}"
# 複数メトリクスのクエリ
curl "http://localhost:4242/api/query?start=1d-ago&m=avg:cpu.usage{host=*}&m=avg:memory.usage{host=*}"
# 集約関数を使用したクエリ
curl "http://localhost:4242/api/query?start=6h-ago&m=avg:rate:network.bytes.in{interface=eth0}"
データモデリング
効果的なタグ設計
// 良い例:適切な粒度のタグ
{
"metric": "http.requests",
"tags": {
"method": "GET",
"status": "200",
"endpoint": "api",
"datacenter": "us-east-1"
}
}
// 避けるべき例:高すぎるカーディナリティ
{
"metric": "http.requests",
"tags": {
"user_id": "12345", // ユーザーIDは数百万になる可能性
"request_id": "abc123" // リクエストIDは無限に増加
}
}
メトリクス命名規則
# 階層的な命名(ドット区切り)
system.cpu.usage
system.memory.free
app.response_time
database.connections.active
cache.hits_per_second
# プレフィックスでカテゴリ分け
prod.web.cpu.usage
dev.api.response_time
monitoring.alerts.count
メトリクス収集
アプリケーション統合例(Java)
import net.opentsdb.client.*;
public class MetricsCollector {
private OpenTSDBClient client;
public MetricsCollector() {
this.client = new OpenTSDBClient("localhost", 4242);
}
public void recordMetric(String metric, double value, Map<String, String> tags) {
DataPoint point = new DataPoint(metric, System.currentTimeMillis() / 1000, value, tags);
client.put(point);
}
// CPU使用率の送信例
public void sendCpuUsage() {
Map<String, String> tags = new HashMap<>();
tags.put("host", "app-server-01");
tags.put("environment", "production");
double cpuUsage = getCpuUsage(); // システムからCPU使用率を取得
recordMetric("system.cpu.usage", cpuUsage, tags);
}
}
Pythonクライアントの例
import requests
import time
import json
class OpenTSDBClient:
def __init__(self, host='localhost', port=4242):
self.base_url = f"http://{host}:{port}"
def put(self, metric, value, tags, timestamp=None):
if timestamp is None:
timestamp = int(time.time())
data = {
"metric": metric,
"timestamp": timestamp,
"value": value,
"tags": tags
}
response = requests.post(
f"{self.base_url}/api/put",
json=data,
headers={'Content-Type': 'application/json'}
)
return response.status_code == 204
# 使用例
client = OpenTSDBClient()
client.put("temperature", 23.5, {"sensor": "room1", "building": "office"})
client.put("humidity", 65.2, {"sensor": "room1", "building": "office"})
実用例
システム監視のダッシュボード構築
# Grafanaとの連携設定
# OpenTSDBデータソースの設定
curl -X POST http://admin:admin@localhost:3000/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "OpenTSDB",
"type": "opentsdb",
"url": "http://localhost:4242",
"access": "proxy"
}'
アラート設定
# Nagiosプラグインを使用したアラート
./check_tsd -H localhost -p 4242 -m cpu.usage -t host=web01 -w 80 -c 90
# カスタムアラートスクリプト
curl "http://localhost:4242/api/query?start=5m-ago&m=avg:cpu.usage{host=web01}" | \
jq '.[] | if .dps | to_entries | .[-1].value > 90 then "CRITICAL: CPU > 90%" else "OK" end'
ベストプラクティス
パフォーマンス最適化
# 設定ファイルの最適化
# バッチサイズの調整
tsd.storage.flush_interval = 1000
# 圧縮の有効化
tsd.storage.enable_compaction = true
# キャッシュサイズの調整
tsd.core.meta.cache.enable = true
tsd.core.meta.cache.size = 1000000
運用監視
# OpenTSDB自体の監視
curl "http://localhost:4242/api/stats"
# HBaseの状態確認
echo "status" | hbase shell
# ログ監視
tail -f /var/log/opentsdb/opentsdb.log
データ保持ポリシー
# 古いデータの削除(HBaseのTTL設定)
echo "alter 'tsdb', {NAME => 'f', TTL => 31536000}" | hbase shell # 1年間保持
# データのコンパクション実行
tsdb fsck --fix-duplicates --compact
スケーリング戦略
# 複数TSDインスタンスの負荷分散設定
# ロードバランサー(HAProxy)設定例
backend opentsdb_cluster
balance roundrobin
server tsd1 192.168.1.10:4242 check
server tsd2 192.168.1.11:4242 check
server tsd3 192.168.1.12:4242 check