# DistributedTimer **Repository Path**: konglinglong/DistributedTimer ## Basic Information - **Project Name**: DistributedTimer - **Description**: 分布式定时器 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-21 - **Last Updated**: 2025-07-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 分布式定时器 (Distributed Timer) 基于Redis的Go语言分布式定时器系统,支持多服务、多实例架构和故障转移功能。 ## 功能特性 - **多服务支持**: 支持多个独立的服务,每个服务有自己的定时器队列 - **多实例架构**: 每个服务下可以有多个实例,实现负载分担 - **故障转移**: 实例故障时,其定时器会自动转移到同服务的其他健康实例 - **心跳检测**: 实时监控实例状态,及时发现故障实例 - **Redis存储**: 使用Redis作为数据存储,保证数据持久性和一致性 - **回调机制**: 支持自定义回调函数处理定时器事件 ## 系统架构 ``` Service1 ├── Instance1 │ ├── Timer1 │ ├── Timer2 │ └── Timer3 ├── Instance2 │ ├── Timer4 │ └── Timer5 └── Instance3 └── Timer6 Service2 ├── Instance4 │ ├── Timer7 │ └── Timer8 └── Instance5 └── Timer9 ``` ## 核心组件 ### 1. 定时器管理器 (DistributedTimer) - 负责定时器的创建、删除和执行 - 管理实例注册和心跳 - 处理故障转移逻辑 ### 2. 定时器 (Timer) - 包含定时器的基本信息:ID、名称、服务、实例、间隔时间等 - 支持不同的执行状态:active、paused、stopped ### 3. 实例 (Instance) - 代表一个定时器服务实例 - 包含实例信息:ID、服务、主机、端口、状态等 ### 4. Redis数据结构 - `timer:{timer_id}`: 定时器详细信息 - `instance:{instance_id}`: 实例详细信息 - `instance_timers:{instance_id}`: 实例拥有的定时器列表 - `service_instances:{service_name}`: 服务中的实例列表 - `timer_queue:{service_name}`: 定时器执行队列(有序集合) ## 安装和使用 ### 1. 安装依赖 ```bash go mod tidy ``` ### 2. 启动Redis ```bash # 使用Docker启动Redis docker run -d -p 6379:6379 redis:latest # 或者直接启动Redis服务 redis-server ``` ### 3. 基本使用示例 ```go package main import ( "log" "time" ) // 定义回调函数 func myCallback(timer *Timer) error { log.Printf("Timer %s executed at %v", timer.Name, time.Now()) return nil } func main() { // 创建分布式定时器实例 dt := NewDistributedTimer("localhost:6379", "service1", "localhost", 8080) // 注册回调函数 dt.RegisterCallback("my_callback", myCallback) // 启动分布式定时器 err := dt.Start() if err != nil { log.Fatal(err) } defer dt.Stop() // 创建定时器(每10秒执行一次) timer, err := dt.CreateTimer("daily_task", 10, "my_callback") if err != nil { log.Fatal(err) } log.Printf("Timer created: %s", timer.ID) // 保持程序运行 select {} } ``` ### 4. 运行示例程序 ```bash # 运行示例程序 go run example.go # 在不同终端运行多个实例模拟服务 go run example.go # 实例1 go run example.go # 实例2 go run example.go # 实例3 ``` ## 故障转移演示 1. 启动多个实例: ```bash # 终端1 go run example.go # 终端2 go run example.go # 终端3 go run example.go ``` 2. 观察定时器在各实例间的分布 3. 强制关闭其中一个实例(Ctrl+C) 4. 观察其他实例自动接管故障实例的定时器 ## 测试 ### 运行单元测试 ```bash # 运行所有测试 go test -v # 运行特定测试 go test -v -run TestDistributedTimer_CreateTimer # 运行故障转移测试 go test -v -run TestDistributedTimer_Failover ``` ### 运行基准测试 ```bash # 运行基准测试 go test -bench=. # 运行特定基准测试 go test -bench=BenchmarkDistributedTimer_CreateTimer ``` ### 测试覆盖率 ```bash # 生成测试覆盖率报告 go test -cover # 生成详细的覆盖率报告 go test -coverprofile=coverage.out go tool cover -html=coverage.out ``` ## API 文档 ### DistributedTimer 方法 #### `NewDistributedTimer(redisAddr, service, host string, port int) *DistributedTimer` 创建新的分布式定时器实例。 #### `RegisterCallback(name string, callback TimerCallback)` 注册回调函数。 #### `Start() error` 启动分布式定时器服务。 #### `Stop() error` 停止分布式定时器服务。 #### `CreateTimer(name string, interval int64, callback string) (*Timer, error)` 创建新的定时器。 - `name`: 定时器名称 - `interval`: 执行间隔(秒) - `callback`: 回调函数名称 #### `DeleteTimer(timerID string) error` 删除指定的定时器。 #### `GetInstanceTimers() ([]*Timer, error)` 获取当前实例的所有定时器。 #### `GetServiceInstances() ([]*Instance, error)` 获取当前服务的所有实例。 ### 回调函数类型 ```go type TimerCallback func(timer *Timer) error ``` 回调函数接收一个Timer指针作为参数,返回error。如果返回非nil错误,会记录日志但不会影响定时器的后续执行。 ## 配置参数 - **心跳间隔**: 5秒(实例向Redis更新心跳的间隔) - **定时器检查间隔**: 1秒(检查是否有定时器需要执行的间隔) - **故障检查间隔**: 10秒(检查故障实例的间隔) - **故障超时**: 30秒(实例心跳超时时间) ## 注意事项 1. **Redis连接**: 确保Redis服务正常运行且网络连接稳定 2. **时钟同步**: 各实例服务器时钟应保持同步 3. **回调函数**: 回调函数应该是幂等的,因为在故障转移时可能会重复执行 4. **资源清理**: 程序退出时应调用`Stop()`方法清理资源 5. **并发安全**: 回调函数应该是并发安全的,因为可能同时执行多个定时器 ## 性能优化建议 1. **Redis连接池**: 在高并发场景下可以配置Redis连接池 2.3. **批量操作**: 对于大量定时器的场景,可以考虑批量操作Redis 4. **分片策略**: 可以根据定时器数量对服务进行分片 5. **监控告警**: 建议添加监控和告警机制 ## 故障排查 ### 常见问题 1. **定时器不执行** - 检查Redis连接 - 检查回调函数是否正确注册 - 检查定时器状态是否为active 2. **故障转移不工作** - 检查实例心跳是否正常 - 检查故障检查间隔设置 - 检查Redis中的实例信息 3. **内存泄漏** - 确保调用Stop()方法 - 检查goroutine是否正常退出 ### 调试技巧 1. 启用详细日志 2. 使用Redis CLI监控数据变化 3. 检查goroutine数量 4. 监控内存使用情况 ## 许可证 MIT License