-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
79 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,87 @@ | ||
package gossip | ||
|
||
import ( | ||
"errors" | ||
"hash/fnv" | ||
"sort" | ||
"sync" | ||
"time" | ||
) | ||
|
||
type Status struct { | ||
Nodes map[string]*Node // 所有已知节点的信息 | ||
Self *Node // 本节点信息 | ||
Mutex sync.Mutex // 保护 Nodes 的并发访问 | ||
Interval time.Duration // 心跳间隔 | ||
LossThresh time.Duration // 失效阈值 | ||
const MinNeighbors = 3 // 最小节点数,奇数 | ||
|
||
type Node struct { | ||
ID string // 节点唯一标识 | ||
Address string // 节点地址 | ||
Heartbeat int // 心跳计数 | ||
Timestamp int64 // 最新心跳时间 | ||
Alive bool // 节点状态 | ||
Hash uint32 // 节点哈希值,用于一致性哈希 | ||
} | ||
|
||
type Cluster struct { | ||
Neighbors map[string]*Node // 所有已知节点的信息 | ||
Self *Node // 本节点信息 | ||
Mutex sync.Mutex // 保护 Nodes 的并发访问 | ||
Interval time.Duration // 心跳间隔 | ||
Timeout time.Duration // 失效阈值 | ||
HashRing []*Node // 一致性哈希存储范围的键 | ||
} | ||
|
||
func NewNode(id, addr string) *Node { | ||
node := &Node{ | ||
ID: id, | ||
Address: addr, | ||
Heartbeat: 0, | ||
Timestamp: time.Now().Unix(), | ||
Alive: true, | ||
} | ||
// 计算节点的哈希值 | ||
node.Hash = NodeHash(id) | ||
return node | ||
} | ||
|
||
func NewCluster(id, addr string, interval, timeout time.Duration) *Cluster { | ||
self := NewNode(id, addr) | ||
return &Cluster{ | ||
Neighbors: map[string]*Node{id: self}, | ||
Self: self, | ||
Interval: interval, | ||
Timeout: timeout, | ||
HashRing: []*Node{self}, // 将自身添加到哈希环,多个节点形成一个哈希环 | ||
} | ||
} | ||
|
||
// AddNodes 批量添加数据节点 | ||
func (c *Cluster) AddNodes(nodes ...Node) error { | ||
c.Mutex.Lock() | ||
defer c.Mutex.Unlock() | ||
|
||
// 必须是奇数数量的节点集群 | ||
if len(nodes) < MinNeighbors { | ||
return errors.New("") | ||
} | ||
|
||
// 设置节点哈希值并将节点加入到邻居中 | ||
for _, node := range nodes { | ||
// 通过节点 ID 算出在哈希环中的值 | ||
node.Hash = NodeHash(node.ID) | ||
c.Neighbors[node.ID] = &node | ||
// 节点对应哈希值也要放到一致性节点环中 | ||
c.HashRing = append(c.HashRing, &node) | ||
} | ||
|
||
// 对一致性哈希环中的节点按哈希值排序 | ||
sort.Slice(c.HashRing, func(i, j int) bool { | ||
return c.HashRing[i].Hash < c.HashRing[j].Hash | ||
}) | ||
|
||
return nil | ||
} | ||
|
||
// NodeHash 计算节点的唯一哈希值 | ||
func NodeHash(key string) uint32 { | ||
h := fnv.New32a() | ||
h.Write([]byte(key)) | ||
return h.Sum32() | ||
} |
This file was deleted.
Oops, something went wrong.