Files
seqlog/example/README.md
bourdon 90cc9e21c9 重构:重命名核心组件并增强查询功能
主要更改:

1. 核心重命名
   - Seqlog -> LogHub (更准确地反映其作为日志中枢的角色)
   - NewSeqlog() -> NewLogHub()
   - LogCursor -> ProcessCursor (更准确地反映其用于处理场景)
   - seqlog_manager.go -> loghub.go (文件名与结构体名对应)

2. TopicProcessor.Reset 增强
   - 如果正在运行且没有待处理的日志,会自动停止后重置
   - 如果有待处理的日志,返回详细错误(显示已处理/总记录数)
   - 简化了 LogHub.ResetTopic,移除显式 Stop 调用

3. 新增查询方法
   - TopicProcessor.QueryFromFirst(count) - 从第一条记录向索引递增方向查询
   - TopicProcessor.QueryFromLast(count) - 从最后一条记录向索引递减方向查询
   - LogHub.QueryFromFirst(topic, count)
   - LogHub.QueryFromLast(topic, count)

4. 测试覆盖
   - 添加 query_test.go - QueryFromProcessing 测试
   - 添加 TestQueryFromFirstAndLast - TopicProcessor 查询测试
   - 添加 TestLogHubQueryFromFirstAndLast - LogHub 查询测试
   - 添加 TestTopicResetWithPendingRecords - Reset 增强功能测试

5. 示例代码
   - 添加 example/get_record/ - 演示 QueryFromProcessing 用法
   - 更新所有示例以使用 LogHub 和新 API

所有测试通过 

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 13:26:21 +08:00

217 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 的详细统计)
**运行方式:**
```bash
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 作为日志聚合器。
**功能演示:**
- 写入和读取日志记录
- 使用索引查询
- 使用游标读取
- 获取统计信息
**运行方式:**
```bash
cd topic_processor
go run main.go
```
### 3. index/ - 索引功能示例
展示索引文件的使用和管理。
**运行方式:**
```bash
cd index
go run main.go
```
### 4. webapp/ - Web 应用示例
一个完整的 Web 应用,展示如何在实际项目中使用 seqlog。
**运行方式:**
```bash
cd webapp
go run main.go
```
然后访问 http://localhost:8080
## 最佳实践
### 并发写入
**推荐做法:** 每个 topic 使用一个专用的 goroutine 进行写入
```go
// 好的做法 - 每个 topic 一个写入 goroutine
for _, topic := range topics {
go func(t string) {
for msg := range msgChan {
seq.Write(t, msg)
}
}(topic)
}
```
**避免做法:** 多个 goroutine 并发写入同一个 topic
```go
// 不推荐 - 多个 goroutine 写入同一个 topic
for i := 0; i < 10; i++ {
go func() {
seq.Write("same-topic", data) // 可能导致数据损坏
}()
}
```
### 并发查询
查询操作是并发安全的,可以多个 goroutine 并发查询:
```go
// 完全安全 - 多个 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 之前先创建目录:
```go
os.MkdirAll("log_dir", 0755)
seq := seqlog.NewLogHub("log_dir", logger, nil)
```
**2. 查询时出现 EOF 错误**
这是正常现象,当 tailer 正在处理文件时可能会读取到不完整的记录。可以:
- 增加查询重试
- 等待文件处理完成后再查询
**3. Handler 没有被调用**
检查:
- Handler 是否正确注册
- Seqlog 是否已启动 (`seq.Start()`)
- 目录和文件权限是否正确
## 更多信息
查看项目根目录的 CLAUDE.md 了解更多开发指南。