本文将引导您基于 SelectDB 搭建一套高性能、低成本的日志存储与分析平台。内容涵盖从资源规划、实例优化、表结构设计,到数据采集与查询分析的全流程。
第一步:规划资源
在创建 SelectDB 实例前,精确的资源评估至关重要,这能确保系统在满足业务需求的同时,实现成本效益最大化。评估主要围绕写入、查询和存储三个维度展开。
评估方法与案例
您可以参考下方的关键指标表,根据您的业务指标估算所需资源。为了方便您理解,我们提供了一个具体案例作为参考。
案例场景:假设某业务每日新增 100 TB 原始日志,数据压缩比为 5:1,热数据保留 3 天,冷数据保留 30 天。写入峰值是平均值的 2 倍,单核写入性能按 10 MB/s 估算。
关键指标参考表
1. 业务指标输入(根据您的业务场景预估) | ||
关键指标 | 案例值 | 说明 |
每日原始数据增量 (TB) | 100 | 每日产生的原始日志总量。 |
数据压缩比 | 5 | 日志数据(包括索引)的典型压缩比为 3:1 到 10:1。 |
热数据存储周期(天) | 3 | 热数据在本地磁盘的存储时长。 |
冷数据存储周期(天) | 30 | 冷数据在对象存储的存储时长。 |
写入峰值/均值比 | 200% | 预估业务写入的峰值,通常为平均值的 2-3 倍。 |
查询预留 CPU 比例 | 50% | 为查询负载预留的 CPU 资源。建议初始值为 50%,后续可根据实际负载进行调整。 |
2. 资源需求计算 | ||
总数据生命周期 (天) | 33 | 计算公式: |
平均写入吞吐 (MB/s) | 1214 | 计算公式: |
峰值写入吞吐 (MB/s) | 2427 | 计算公式: |
写入所需 CPU 核数 (峰值) | 242.7 | 计算公式: |
BE 节点总 CPU 核数 | 485.4 | 计算公式: |
本地磁盘所需空间 (TB) | 60 | 计算公式: 注:本案例计算时副本数取 1,生产环境建议设为 3 以保证高可用。 |
对象存储所需空间 (TB) | 600 | 计算公式: 注:本案例计算时副本数取 1。 |
估算结论
根据以上估算,该案例的推荐资源配置如下:
BE 节点:总计约 480 vCPU 和 1920 GB 内存 (vCPU:内存建议为 1:4)。
对象存储:约 600 TB,用于存储冷数据。
第二步:优化实例配置
实例创建后,建议您针对日志场景优化 FE 和 BE 的参数,以提升写入、压缩和查询性能。在创建实例时,在应用场景中选择日志分析场景;或在配置管理界面应用日志分析场景配置模板。
以下是日志分析场景的核心参数建议,您可以根据实际需求进行调整。
FE 配置
参数 | 配置目的与说明 |
| 目的:提升动态分桶灵活性。 将自动分桶的最小分桶数从 1 调大到 10,以应对日志量快速增长时可能出现的分桶不足问题。 |
BE 配置
参数 | 配置目的与说明 |
| 目的:加速冷数据查询。 开启文件缓存,将访问过的对象存储数据缓存到本地磁盘。 |
| 目的:提升写入性能。 将 MemTable 写入缓冲区大小增加至 1 GB,以减少小文件生成。 |
| 目的:防止高频写入被阻塞。 配合 `time_series` Compaction 策略,该参数允许更多数据版本在后台异步合并,从而避免因版本数超限而阻塞写入。 |
| 目的:平衡系统资源。 建议将该参数设置为 BE 节点 CPU 核数的 1/4。这有助于平衡系统资源:约 1/4 CPU 用于写入,1/4 用于后台 Compaction,剩余 1/2 留给查询。 |
| 目的:降低查询 CPU 消耗。 在 Compaction 过程中合并倒排索引,以减少索引文件数量,从而降低查询时的 CPU 消耗。 |
| 目的:节约系统资源。 关闭在日志场景下非必需的 Compaction 功能,以节约系统资源。 |
| 目的:提升 Compaction 整体效率。 在日志场景下,所有 Compaction 任务同等重要。关闭优先级调度可以避免因磁盘并发限制而影响整体效率。 |
| 目的:适配 `time_series` 策略。 调整 Compaction 任务的内存控制参数,以适配 `time_series` 策略。 |
| 目的:提升全文检索性能。 由于日志数据量大,Page Cache 的缓存命中率通常较低。建议关闭 Page Cache,并将节省的内存(例如 30%)分配给倒排索引缓存,以提升全文检索性能。 |
| 目的:提高常用索引的缓存命中率。 将倒排索引在内存中的缓存保留时间延长至 1 小时,以提高常用索引的缓存命中率。 |
| 目的:优化写入性能与冷数据查询。 开启索引在数据下沉至对象存储时自动缓存的功能,以加速冷数据查询。同时,关闭写入时缓存索引的功能,以优化写入性能。 |
第三步:设计日志表结构
合理的表结构是发挥 SelectDB 性能的关键。针对日志数据的写入和查询特点,我们推荐采用以下建表策略。
以下是一个典型的日志表建表示例,其中包含了多项针对性的优化配置:
CREATE DATABASE log_db;
USE log_db;
CREATE TABLE log_table
(
`ts` DATETIME,
`host` TEXT,
`path` TEXT,
`message` TEXT,
-- 对需要过滤的字段创建倒排索引,加速文本检索
INDEX idx_host (`host`) USING INVERTED,
INDEX idx_path (`path`) USING INVERTED,
-- 对 message 字段创建倒排索引,并配置分词器以支持全文检索
INDEX idx_message (`message`) USING INVERTED PROPERTIES("parser" = "unicode", "support_phrase" = "true")
)
ENGINE = OLAP
DUPLICATE KEY(`ts`) -- 使用时间戳作为排序键,加速时序查询
PARTITION BY RANGE(`ts`) () -- 按时间进行范围分区
DISTRIBUTED BY RANDOM BUCKETS 20 -- 使用随机分桶,提升写入效率
PROPERTIES (
"compression" = "zstd", -- 使用 zstd 压缩算法,兼顾压缩比与性能
"compaction_policy" = "time_series", -- 采用 time_series compaction 策略,优化时序数据写入
-- 开启并配置动态分区,实现分区的自动管理
"dynamic_partition.enable" = "true",
"dynamic_partition.create_history_partition" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-30",
"dynamic_partition.end" = "1",
"dynamic_partition.prefix" = "p",
"dynamic_partition.buckets" = "60"
);关键配置说明
分区与排序:优化时序数据管理与查询
分区策略:使用时间字段(如 `ts`)进行 Range 分区(
PARTITION BY RANGE(ts)),并开启动态分区("dynamic_partition.enable" = "true")。系统将根据您的配置自动创建和删除分区,从而极大简化数据生命周期管理。排序键:使用时间字段作为排序键(
DUPLICATE KEY(ts)),可以加速“查询最新的 N 条日志”这类时序查询。
分桶:提升写入并发与负载均衡
分桶策略:使用随机分桶(
DISTRIBUTED BY RANDOM),配合导入参数 `load_to_single_tablet`,可以有效提升批量写入效率并避免写倾斜。建议您根据数据量规划分桶数,使每个分桶压缩后的数据量保持在 1-10 GB 范围内。
Compaction 与压缩:降低存储成本与写放大
Compaction 策略:务必使用 `time_series` 策略(
"compaction_policy" = "time_series")。该策略专为时序数据设计,可以显著降低高并发写入场景下的写放大和资源消耗。压缩算法:推荐使用 `zstd` 压缩算法(
"compression" = "zstd"),它在提供较高压缩比的同时,也具有良好的解压性能。
索引:加速文本检索与过滤
倒排索引:对需要作为筛选条件的字段(例如 `host`、`path`、`message`)创建倒排索引(
USING INVERTED),以加速文本检索和等值查询。全文检索:对于需要进行全文检索的字段(例如 `message`),建议将分词器(parser)设置为 `unicode` 以支持中英文混合分词。如果您需要进行短语精确匹配查询,请开启 `support_phrase`;否则建议关闭该选项,以节约存储空间和索引开销。
更多建表指引,请参考 第三步:学习数据库表设计要点。
第四步:采集与导入日志
SelectDB 兼容 Apache Doris 的数据导入 API,可以与 Logstash、Filebeat、Kafka 等主流采集工具无缝集成。本节将介绍如何配置这些工具,从而高效地将日志数据导入 SelectDB。
Logstash
下载并安装 Logstash Doris Output 插件,支持以下两种方式:
直接下载:点此下载。
从源码编译,并运行下方命令安装:
./bin/logstash-plugin install logstash-output-doris-1.2.0.gem
配置 Logstash。需配置以下参数:
logstash.yml:配置 Logstash 批处理日志的条数和时间,用于提升数据写入性能。pipeline.batch.size: 1000000 pipeline.batch.delay: 10000logstash_demo.conf:配置所采集日志的具体输入路径和输出到 SelectDB 的设置。input { file { path => "/path/to/your/log" } } output { doris { http_hosts => [ "<http://fehost1:http_port>", "<http://fehost2:http_port>", "<http://fehost3:http_port">] user => "your_username" password => "your_password" db => "your_db" table => "your_table" # doris stream load http headers headers => { "format" => "json" "read_json_by_line" => "true" "load_to_single_tablet" => "true" } # field mapping: doris fileld name => logstash field name # %{} to get a logstash field, [] for nested field such as [host][name] for host.name mapping => { "ts" => "%{@timestamp}" "host" => "%{[host][name]}" "path" => "%{[log][file][path]}" "message" => "%{message}" } log_request => true log_speed_interval => 10 } }
按照下方命令运行 Logstash,采集日志并输出至 SelectDB。
./bin/logstash -f logstash_demo.conf
更多关于 Logstash 配置和使用的说明,可参考 Logstash Doris Output Plugin。
Filebeat
获取支持输出至 SelectDB 的 Filebeat 二进制文件:下载地址。
配置 Filebeat。需配置以下参数:
filebeat_demo.yml:配置所采集日志的具体输入路径和输出到 SelectDB 的设置。# input filebeat.inputs: - type: log enabled: true paths: - /path/to/your/log # multiline 可以将跨行的日志(比如 Java stacktrace)拼接起来 multiline: type: pattern # 效果:以 yyyy-mm-dd HH:MM:SS 开头的行认为是一条新的日志,其他都拼接到上一条日志 pattern: '^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}' negate: true match: after skip_newline: true processors: # 用 js script 插件将日志中的 \t 替换成空格,避免 JSON 解析报错 - script: lang: javascript source: > function process(event) { var msg = event.Get("message"); msg = msg.replace(/\t/g, " "); event.Put("message", msg); } # 用 dissect 插件做简单的日志解析 - dissect: # 2024-06-08 18:26:25,481 INFO (report-thread|199) [ReportHandler.cpuReport():617] begin to handle tokenizer: "%{day} %{time} %{log_level} (%{thread}) [%{position}] %{content}" target_prefix: "" ignore_failure: true overwrite_keys: true # queue and batch queue.mem: events: 1000000 flush.min_events: 100000 flush.timeout: 10s # output output.doris: fenodes: [ "http://fehost1:http_port", "http://fehost2:http_port", "http://fehost3:http_port" ] user: "your_username" password: "your_password" database: "your_db" table: "your_table" # output string format ## %{[agent][hostname]} %{[log][file][path]} 是filebeat自带的metadata ## 常用的 filebeat metadata 还是有采集时间戳 %{[@timestamp]} ## %{[day]} %{[time]} 是上面 dissect 解析得到字段 codec_format_string: '{"ts": "%{[day]} %{[time]}", "host": "%{[agent][hostname]}", "path": "%{[log][file][path]}", "message": "%{[message]}"}' headers: format: "json" read_json_by_line: "true" load_to_single_tablet: "true"
按照下方命令运行 Filebeat,采集日志并输出至 SelectDB。
chmod +x filebeat-doris-2.1.1 ./filebeat-doris-2.1.1 -c filebeat_demo.yml
更多关于 Filebeat 配置和使用的说明,可参考 Beats Doris Output Plugin。
Kafka
将 JSON 格式的日志写入 Kafka 的消息队列,创建 Kafka Routine Load,即可让 SelectDB 从 Kafka 主动拉取数据。
可参考如下示例。其中,property.× 是 Librdkafka 客户端相关配置,根据实际 Kafka 集群情况配置。
-- 准备好 kafka 集群和 topic log__topic_
-- 创建 routine load,从 kafka log__topic_将数据导入 log_table 表
CREATE ROUTINE LOAD load_log_kafka ON log_db.log_table
COLUMNS(ts, clientip, request, status, size)
PROPERTIES (
"max_batch_interval" = "60",
"max_batch_rows" = "20000000",
"max_batch_size" = "1073741824",
"load_to_single_tablet" = "true",
"format" = "json"
)
FROM KAFKA (
"kafka_broker_list" = "host:port",
"kafka_topic" = "log__topic_",
"property.group.id" = "your_group_id",
"property.security.protocol"="SASL_PLAINTEXT",
"property.sasl.mechanism"="GSSAPI",
"property.sasl.kerberos.service.name"="kafka",
"property.sasl.kerberos.keytab"="/path/to/xxx.keytab",
"property.sasl.kerberos.principal"="<xxx@yyy.com>"
);
-- 查看 routine 的状态
SHOW ROUTINE LOAD;更多关于 Kafka 配置和使用的说明,可参考Routine Load。
自定义程序采集日志
可通过 HTTP API Stream Load 自定义程序将日志数据导入 SelectDB。示例代码:
curl
--location-trusted
-u username:password
-H "format:json"
-H "read_json_by_line:true"
-H "load_to_single_tablet:true"
-H "timeout:600"
-T logfile.json
http://fe_host:fe_http_port/api/log_db/log_table/_stream_load
在使用自定义程序时,需注意以下关键点:
使用 Basic Auth 进行 HTTP 鉴权,用命令
echo -n 'username:password' | base64进行计算。设置 HTTP header "format:json",指定数据格式为 JSON。
设置 HTTP header "read_json_by_line:true",指定每行一个 JSON。
设置 HTTP header "load_to_single_tablet:true",指定一次导入写入一个分桶减少导入的小文件。
建议写入客户端单个 Batch 大小为 100MB~1GB。Apache Doris 2.1 及更高版本需通过服务端 Group Commit 功能降低客户端 Batch 大小。
第五步:查询与分析日志
数据成功导入后,您可以通过标准 SQL 或可视化平台对日志进行查询和分析。
使用 SQL 进行查询
SelectDB 兼容 MySQL 协议,因此您可以使用任何 MySQL 客户端或通过 JDBC/ODBC 连接到集群,并执行 SQL 进行查询分析。
mysql -h fe_host -P fe_mysql_port -u your_username -D log_db以下是一些常见的日志查询示例:
查看最新的 10 条日志
SELECT * FROM log_table ORDER BY ts DESC LIMIT 10;查询指定 `host` 的最新 10 条日志
SELECT * FROM log_table WHERE host = '8.8.8.8' ORDER BY ts DESC LIMIT 10;全文检索:查询 `message` 字段中包含 `error` 或 `404` 的日志
SELECT * FROM log_table WHERE message MATCH_ANY 'error 404' ORDER BY ts DESC LIMIT 10;全文检索:查询 `message` 字段中同时包含 `image` 和 `faq` 的日志
SELECT * FROM log_table WHERE message MATCH_ALL 'image faq' ORDER BY ts DESC LIMIT 10;全文检索:查询 `message` 字段中包含精确短语 `image faq` 的日志
SELECT * FROM log_table WHERE message MATCH_PHRASE 'image faq' ORDER BY ts DESC LIMIT 10;
可视化日志分析
云数据库 SelectDB 集成了数据开发与管理工具作为可视化日志分析平台。使用说明参考数据开发与管理。
支持全文检索和 SQL 两种模式。
支持在时间框和直方图上选择查询日志的时间段。
支持日志明细展示,可展开为 JSON 或表格格式。
支持在日志数据上交互式添加和删除筛选条件。
搜索结果的字段 Top 值展示,便于发现异常值和进一步下钻分析。