Files
seqlog/example
bourdon 810664eb12 重构:优化记录格式并修复核心功能
- 修改记录存储格式为 [4B len][8B offset][4B CRC][16B UUID][data]
- 修复 TopicProcessor 中 WaitGroup 使用错误导致 handler 不执行的问题
- 修复写入保护逻辑,避免 dirtyOffset=-1 时误判为写入中
- 添加统计信息定期持久化功能
- 改进 UTF-8 字符截断处理,防止 CJK 字符乱码
- 优化 Web UI:显示人类可读的文件大小,支持点击外部关闭弹窗
- 重构示例代码,添加 webui 和 webui_integration 示例

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 17:54:49 +08:00
..

Seqlog 示例

本目录包含 seqlog 的使用示例。

示例列表

1. concurrent/ - 高并发示例

展示 seqlog 在高并发场景下的性能表现。

运行时间:约 5 分钟

场景覆盖:

  • 场景 1: 并发写入不同 topic3 个 topic每个 2000 条消息,共 6000 条)
  • 场景 2: 并发查询20 个 goroutine每个执行 200 次查询,共 4000 次)
  • 场景 3: 混合读写3 个写入 goroutine + 10 个查询 goroutine 同时运行)
  • 场景 4: 持续压测(运行 4 分钟,持续写入和查询,实时显示进度)
  • 场景 5: 统计信息汇总(显示所有 topic 的详细统计)

运行方式:

cd concurrent
go run main.go

注意: 这个示例需要运行约 5 分钟,请耐心等待。

预期输出:

=== Seqlog 高并发示例 ===
预计运行时间: 约 5 分钟

场景 1: 并发写入测试(每个 goroutine 写入不同 topic
  - 3 个 topic每个 topic 一个专用写入 goroutine
  - 每个 goroutine 写入 2000 条消息

写入完成:
  总消息数: 6000
  错误数: 0
  耗时: 27s
  吞吐量: 222 msg/s

场景 2: 并发查询测试
  - 20 个 goroutine 并发查询
  - 每个 goroutine 执行 200 次查询操作

查询完成:
  总查询数: 3900
  错误数: 100
  耗时: 10s
  吞吐量: 390 query/s

场景 3: 混合读写测试
  - 3 个写入 goroutine每个 topic 一个),每个写入 1000 条消息
  - 10 个查询 goroutine每个执行 200 次查询
  - 同时进行

混合操作完成:
  写入: 3000 条消息
  查询: 1900 次
  耗时: 14s

场景 4: 持续压测(运行 4 分钟)
  - 3 个写入 goroutine 持续写入
  - 5 个查询 goroutine 持续查询
  - 实时显示进度

  [进度] 已运行 10 秒 - 写入: 2400 条, 查询: 2000 次
  [进度] 已运行 20 秒 - 写入: 4800 条, 查询: 4000 次
  [进度] 已运行 30 秒 - 写入: 7200 条, 查询: 6000 次
  ...

持续压测完成:
  运行时间: 4m0s
  写入: 57600 条消息
  查询: 48000 次
  写入速率: 240 msg/s
  查询速率: 200 query/s

场景 5: 统计信息汇总
...

场景耗时总结:
  场景 1 (并发写入):     27s
  场景 2 (并发查询):     10s
  场景 3 (混合读写):     14s
  场景 4 (持续压测):     4m0s
  总运行时间:           5m1s (5.0 分钟)

性能指标:

  • 写入吞吐量:~235 msg/s
  • 查询吞吐量:~403 query/s
  • 并发处理:支持多个 topic 同时读写

注意事项:

  • 每个 topic 应该由单个 goroutine 写入,避免并发写入同一文件
  • 多个 goroutine 可以并发查询同一或不同的 topic
  • 查询时可能遇到少量 EOF 错误(因为 tailer 正在处理文件)

2. topic_processor/ - TopicProcessor 基础示例

展示如何使用 TopicProcessor 作为日志聚合器。

功能演示:

  • 写入和读取日志记录
  • 使用索引查询
  • 使用游标读取
  • 获取统计信息

运行方式:

cd topic_processor
go run main.go

3. index/ - 索引功能示例

展示索引文件的使用和管理。

运行方式:

cd index
go run main.go

4. webapp/ - Web 应用示例

一个完整的 Web 应用,展示如何在实际项目中使用 seqlog。

运行方式:

cd webapp
go run main.go

然后访问 http://localhost:8080

最佳实践

并发写入

推荐做法: 每个 topic 使用一个专用的 goroutine 进行写入

// 好的做法 - 每个 topic 一个写入 goroutine
for _, topic := range topics {
    go func(t string) {
        for msg := range msgChan {
            seq.Write(t, msg)
        }
    }(topic)
}

避免做法: 多个 goroutine 并发写入同一个 topic

// 不推荐 - 多个 goroutine 写入同一个 topic
for i := 0; i < 10; i++ {
    go func() {
        seq.Write("same-topic", data) // 可能导致数据损坏
    }()
}

并发查询

查询操作是并发安全的,可以多个 goroutine 并发查询:

// 完全安全 - 多个 goroutine 并发查询
for i := 0; i < 20; i++ {
    go func() {
        processor, _ := seq.GetProcessor("topic")
        results, _ := processor.QueryNewest(count-1, 10)
        // 处理结果...
    }()
}

性能优化

  1. 批量写入:尽可能批量写入数据
  2. 控制查询频率:避免过于频繁的查询操作
  3. 合理设置 PollInterval:根据实际需求调整 tailer 的轮询间隔
  4. 及时关闭资源:使用 defer 确保资源被正确释放

问题排查

常见错误

1. "no such file or directory" 错误

确保在创建 LogHub 之前先创建目录:

os.MkdirAll("log_dir", 0755)
seq := seqlog.NewLogHub("log_dir", logger, nil)

2. 查询时出现 EOF 错误

这是正常现象,当 tailer 正在处理文件时可能会读取到不完整的记录。可以:

  • 增加查询重试
  • 等待文件处理完成后再查询

3. Handler 没有被调用

检查:

  • Handler 是否正确注册
  • Seqlog 是否已启动 (seq.Start())
  • 目录和文件权限是否正确

更多信息

查看项目根目录的 CLAUDE.md 了解更多开发指南。