diff --git a/README.md b/README.md index 1f83c29..8cd6033 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ docker run -p 8080:8080 -v $(pwd)/config:/root/config s3-balance - `server`:监听地址与超时时间。 - `database`:GORM 支持 sqlite/mysql/postgres,并存储对象元数据、分片会话等。 - `buckets`:列出真实与虚拟桶。`virtual: true` 的条目会对外暴露,真实桶为 `virtual: false`。可设置 `path_style` 与 `max_size`。 -- `balancer`:策略 (`round-robin`|`least-space`|`weighted`|`consistent-hash`)、健康检查周期、重试次数与延迟。 +- `balancer`:策略 (`round-robin`|`least-space`|`weighted`)、健康检查周期、重试次数与延迟。 - `metrics`:是否启用 Prometheus 指标及路径。 - `s3api`:Access/Secret Key、`proxy_mode`(true=服务代理,false=重定向)、`auth_required`(Basic Auth)、`virtual_host`(Host-style 路由)。 diff --git a/config/config.example.yaml b/config/config.example.yaml index f9d7ffc..72f8dda 100644 --- a/config/config.example.yaml +++ b/config/config.example.yaml @@ -103,7 +103,6 @@ balancer: # - "round-robin": 轮询 # - "least-space": 选择剩余空间最多的存储桶 # - "weighted": 基于权重的随机选择 - # - "consistent-hash": 一致性哈希(相同的key总是选择相同的存储桶) strategy: "least-space" # 健康检查周期 diff --git a/internal/balancer/balancer.go b/internal/balancer/balancer.go index 96e2146..a1ae5c2 100644 --- a/internal/balancer/balancer.go +++ b/internal/balancer/balancer.go @@ -30,8 +30,6 @@ func NewBalancer(manager *bucket.Manager, cfg *config.BalancerConfig) (*Balancer strategy = NewLeastSpaceStrategy() case "weighted": strategy = NewWeightedStrategy() - case "consistent-hash": - strategy = NewConsistentHashStrategy() default: return nil, fmt.Errorf("unknown balancer strategy: %s", cfg.Strategy) } @@ -124,8 +122,6 @@ func (b *Balancer) SetStrategy(strategyName string) error { strategy = NewLeastSpaceStrategy() case "weighted": strategy = NewWeightedStrategy() - case "consistent-hash": - strategy = NewConsistentHashStrategy() default: return fmt.Errorf("unknown balancer strategy: %s", strategyName) } diff --git a/internal/balancer/consistent_hash.go b/internal/balancer/consistent_hash.go deleted file mode 100644 index 2fd7316..0000000 --- a/internal/balancer/consistent_hash.go +++ /dev/null @@ -1,112 +0,0 @@ -package balancer - -import ( - "crypto/md5" - "encoding/binary" - "fmt" - "sort" - "sync" - - "github.com/DullJZ/s3-balance/internal/bucket" -) - -// ConsistentHashStrategy 一致性哈希策略 -// 使用一致性哈希算法,确保相同的key总是映射到相同的存储桶 -// 当存储桶增加或减少时,能够最小化数据迁移 -type ConsistentHashStrategy struct { - replicas int // 每个节点的虚拟节点数 - ring map[uint32]*bucket.BucketInfo // 哈希环 - nodes []uint32 // 排序的哈希值列表 - mu sync.RWMutex // 读写锁,保护并发访问 -} - -// NewConsistentHashStrategy 创建一致性哈希策略 -func NewConsistentHashStrategy() *ConsistentHashStrategy { - return &ConsistentHashStrategy{ - replicas: 100, // 每个节点的虚拟节点数,越大分布越均匀 - ring: make(map[uint32]*bucket.BucketInfo), - } -} - -// SelectBucket 选择存储桶(基于一致性哈希) -// 相同的key总是会映射到相同的存储桶 -func (s *ConsistentHashStrategy) SelectBucket(buckets []*bucket.BucketInfo, key string, size int64) (*bucket.BucketInfo, error) { - if len(buckets) == 0 { - return nil, fmt.Errorf("no buckets available") - } - - // 更新哈希环 - s.updateRing(buckets) - - // 计算key的哈希值 - hash := s.hash(key) - - // 在环上找到第一个大于等于hash的节点 - s.mu.RLock() - defer s.mu.RUnlock() - - // 二分查找第一个大于等于hash的节点 - idx := sort.Search(len(s.nodes), func(i int) bool { - return s.nodes[i] >= hash - }) - - // 如果没找到,返回第一个节点(环形结构) - if idx == len(s.nodes) { - idx = 0 - } - - return s.ring[s.nodes[idx]], nil -} - -// updateRing 更新哈希环 -// 为每个存储桶创建多个虚拟节点,使哈希分布更均匀 -func (s *ConsistentHashStrategy) updateRing(buckets []*bucket.BucketInfo) { - s.mu.Lock() - defer s.mu.Unlock() - - // 清空现有环 - s.ring = make(map[uint32]*bucket.BucketInfo) - s.nodes = nil - - // 为每个存储桶添加虚拟节点 - for _, b := range buckets { - for i := 0; i < s.replicas; i++ { - // 为每个虚拟节点生成唯一的key - virtualKey := fmt.Sprintf("%s-%d", b.Config.Name, i) - hash := s.hash(virtualKey) - s.ring[hash] = b - s.nodes = append(s.nodes, hash) - } - } - - // 排序节点,便于二分查找 - sort.Slice(s.nodes, func(i, j int) bool { - return s.nodes[i] < s.nodes[j] - }) -} - -// hash 计算哈希值 -// 使用MD5算法,取前4个字节作为uint32 -func (s *ConsistentHashStrategy) hash(key string) uint32 { - h := md5.Sum([]byte(key)) - return binary.BigEndian.Uint32(h[:4]) -} - -// Name 返回策略名称 -func (s *ConsistentHashStrategy) Name() string { - return "consistent-hash" -} - -// SetReplicas 设置虚拟节点数 -// 虚拟节点越多,负载分布越均匀,但内存使用也越多 -func (s *ConsistentHashStrategy) SetReplicas(replicas int) { - s.mu.Lock() - defer s.mu.Unlock() - - if replicas > 0 { - s.replicas = replicas - // 清空现有环,下次选择时会重新构建 - s.ring = make(map[uint32]*bucket.BucketInfo) - s.nodes = nil - } -} diff --git a/internal/config/config.go b/internal/config/config.go index 0b723e5..2bb95b3 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -44,7 +44,7 @@ type BucketConfig struct { // BalancerConfig 负载均衡配置 type BalancerConfig struct { - Strategy string `yaml:"strategy"` // 负载均衡策略: "round-robin", "least-space", "weighted", "consistent-hash" + Strategy string `yaml:"strategy"` // 负载均衡策略: "round-robin", "least-space", "weighted" HealthCheckPeriod time.Duration `yaml:"health_check_period"` // 健康检查周期 UpdateStatsPeriod time.Duration `yaml:"update_stats_period"` // 统计更新周期 RetryAttempts int `yaml:"retry_attempts"` // 重试次数