package sharding import ( "fmt" "time" ) // ShardingStrategy 分表策略接口 type ShardingStrategy interface { // GetTableName 根据时间获取表名 GetTableName(baseTableName string, t time.Time) string // GetCurrentTableName 获取当前表名 GetCurrentTableName(baseTableName string) string // GetTableNamesByRange 根据时间范围获取所有可能的表名 GetTableNamesByRange(baseTableName string, start, end time.Time) []string // GetNextTableName 根据当前表名获取下一个表名(用于动态分表) GetNextTableName(currentTableName string) string // IsNewPeriod 检查是否应该开始新的分表周期 IsNewPeriod(lastTableTime, currentTime time.Time) bool } // MonthlyShardingStrategy 按月分表策略 - 每月第一天分表 type MonthlyShardingStrategy struct{} func NewMonthlyShardingStrategy() ShardingStrategy { return &MonthlyShardingStrategy{} } func (s *MonthlyShardingStrategy) GetTableName(baseTableName string, t time.Time) string { return fmt.Sprintf("%s_%d%02d", baseTableName, t.Year(), t.Month()) } func (s *MonthlyShardingStrategy) GetCurrentTableName(baseTableName string) string { return s.GetTableName(baseTableName, time.Now()) } func (s *MonthlyShardingStrategy) GetTableNamesByRange(baseTableName string, start, end time.Time) []string { var tableNames []string current := time.Date(start.Year(), start.Month(), 1, 0, 0, 0, 0, start.Location()) endMonth := time.Date(end.Year(), end.Month(), 1, 0, 0, 0, 0, end.Location()) for !current.After(endMonth) { tableNames = append(tableNames, s.GetTableName(baseTableName, current)) current = current.AddDate(0, 1, 0) } return tableNames } func (s *MonthlyShardingStrategy) GetNextTableName(currentTableName string) string { // 解析当前表名,生成下一个序号的表名 // 例如: log_202408 -> log_202408_01, log_202408_01 -> log_202408_02 // 简单实现:在表名后添加序号 return fmt.Sprintf("%s_01", currentTableName) } func (s *MonthlyShardingStrategy) IsNewPeriod(lastTableTime, currentTime time.Time) bool { // 检查是否到了新的月份 lastMonth := time.Date(lastTableTime.Year(), lastTableTime.Month(), 1, 0, 0, 0, 0, lastTableTime.Location()) currentMonth := time.Date(currentTime.Year(), currentTime.Month(), 1, 0, 0, 0, 0, currentTime.Location()) return currentMonth.After(lastMonth) } // DailyShardingStrategy 按日分表策略 - 每天分表 type DailyShardingStrategy struct{} func NewDailyShardingStrategy() ShardingStrategy { return &DailyShardingStrategy{} } func (s *DailyShardingStrategy) GetTableName(baseTableName string, t time.Time) string { return fmt.Sprintf("%s_%d%02d%02d", baseTableName, t.Year(), t.Month(), t.Day()) } func (s *DailyShardingStrategy) GetCurrentTableName(baseTableName string) string { return s.GetTableName(baseTableName, time.Now()) } func (s *DailyShardingStrategy) GetTableNamesByRange(baseTableName string, start, end time.Time) []string { var tableNames []string current := time.Date(start.Year(), start.Month(), start.Day(), 0, 0, 0, 0, start.Location()) endDay := time.Date(end.Year(), end.Month(), end.Day(), 0, 0, 0, 0, end.Location()) for !current.After(endDay) { tableNames = append(tableNames, s.GetTableName(baseTableName, current)) current = current.AddDate(0, 0, 1) // 每次增加一天 } return tableNames } func (s *DailyShardingStrategy) GetNextTableName(currentTableName string) string { // 日度分表的序号表名 return fmt.Sprintf("%s_01", currentTableName) } func (s *DailyShardingStrategy) IsNewPeriod(lastTableTime, currentTime time.Time) bool { // 检查是否到了新的一天 lastDay := time.Date(lastTableTime.Year(), lastTableTime.Month(), lastTableTime.Day(), 0, 0, 0, 0, lastTableTime.Location()) currentDay := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 0, 0, 0, 0, currentTime.Location()) return currentDay.After(lastDay) }