Remove consistent hash

This commit is contained in:
DullJZ
2025-10-01 20:47:50 +08:00
parent 48bc2d9b11
commit c2de062070
5 changed files with 2 additions and 119 deletions

View File

@@ -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 路由)。

View File

@@ -103,7 +103,6 @@ balancer:
# - "round-robin": 轮询
# - "least-space": 选择剩余空间最多的存储桶
# - "weighted": 基于权重的随机选择
# - "consistent-hash": 一致性哈希相同的key总是选择相同的存储桶
strategy: "least-space"
# 健康检查周期

View File

@@ -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)
}

View File

@@ -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
}
}

View File

@@ -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"` // 重试次数