# Seqlog 示例 本目录包含 seqlog 的使用示例。 ## 示例列表 ### 1. concurrent_example.go - 高并发示例 展示 seqlog 在高并发场景下的性能表现。 **运行时间:约 5 分钟** **场景覆盖:** - **场景 1**: 并发写入不同 topic(3 个 topic,每个 2000 条消息,共 6000 条) - **场景 2**: 并发查询(20 个 goroutine,每个执行 200 次查询,共 4000 次) - **场景 3**: 混合读写(3 个写入 goroutine + 10 个查询 goroutine 同时运行) - **场景 4**: 持续压测(运行 4 分钟,持续写入和查询,实时显示进度) - **场景 5**: 统计信息汇总(显示所有 topic 的详细统计) **运行方式:** ```bash go run concurrent_example.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_example.go - TopicProcessor 基础示例 展示如何使用 TopicProcessor 作为日志聚合器。 **功能演示:** - 写入和读取日志记录 - 使用索引查询 - 使用游标读取 - 获取统计信息 **运行方式:** ```bash go run topic_processor_example.go ``` ### 3. index_example.go - 索引功能示例 展示索引文件的使用和管理。 **运行方式:** ```bash go run index_example.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" 错误** 确保在创建 Seqlog 之前先创建目录: ```go os.MkdirAll("log_dir", 0755) seq := seqlog.NewSeqlog("log_dir", logger, nil) ``` **2. 查询时出现 EOF 错误** 这是正常现象,当 tailer 正在处理文件时可能会读取到不完整的记录。可以: - 增加查询重试 - 等待文件处理完成后再查询 **3. Handler 没有被调用** 检查: - Handler 是否正确注册 - Seqlog 是否已启动 (`seq.Start()`) - 目录和文件权限是否正确 ## 更多信息 查看项目根目录的 CLAUDE.md 了解更多开发指南。