面试题答案
一键面试设计思路
- 互斥锁(Mutex):用于保护共享资源,确保同一时间只有一个节点能够访问共享资源,防止数据竞争。
- 条件变量(Cond):基于互斥锁工作,用于线程间的同步通信。当共享资源的状态发生变化时,通过条件变量通知等待的节点。
- 网络通信处理:在Go中,可以使用
net
包来实现节点间的网络通信。由于网络通信不可靠,需要加入重试机制和超时处理。 - 可扩展性:设计中采用模块化的方式,节点的增加和减少不会对整体逻辑造成较大影响。例如,每个节点可以作为一个独立的Go协程运行,通过消息队列等方式进行通信,便于扩展节点数量。
- 容错性:当某个节点出现故障时,其他节点可以继续工作。可以通过心跳机制来检测节点的健康状态,当发现某个节点长时间无响应时,将其从系统中剔除。
关键代码片段
package main
import (
"fmt"
"sync"
"time"
)
// 共享资源结构体
type SharedResource struct {
data int
mu sync.Mutex
cond *sync.Cond
}
// 初始化共享资源
func NewSharedResource() *SharedResource {
res := &SharedResource{}
res.cond = sync.NewCond(&res.mu)
return res
}
// 获取共享资源
func (r *SharedResource) Get() int {
r.mu.Lock()
defer r.mu.Unlock()
return r.data
}
// 设置共享资源
func (r *SharedResource) Set(newData int) {
r.mu.Lock()
r.data = newData
r.cond.Broadcast() // 通知所有等待的节点共享资源已更新
r.mu.Unlock()
}
// 等待共享资源更新
func (r *SharedResource) WaitForUpdate() {
r.mu.Lock()
defer r.mu.Unlock()
r.cond.Wait() // 等待条件变量通知
}
// 模拟节点间通信的函数
func communicate(nodeID int, sharedRes *SharedResource) {
// 模拟网络延迟
time.Sleep(time.Duration(nodeID) * time.Second)
// 获取共享资源
data := sharedRes.Get()
fmt.Printf("Node %d got data: %d\n", nodeID, data)
// 模拟修改共享资源
newData := data + nodeID
sharedRes.Set(newData)
fmt.Printf("Node %d set new data: %d\n", nodeID, newData)
// 等待共享资源更新
sharedRes.WaitForUpdate()
fmt.Printf("Node %d notified of update\n", nodeID)
}
func main() {
sharedRes := NewSharedResource()
var wg sync.WaitGroup
// 启动多个节点
for i := 1; i <= 3; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
communicate(id, sharedRes)
}(i)
}
wg.Wait()
}
上述代码展示了如何利用Go的互斥锁和条件变量来保护共享资源,并实现节点间的同步。在实际的分布式系统中,还需要结合网络通信、节点健康检测等功能来实现完整的健壮机制。例如,使用net/http
或gRPC
来实现节点间的网络通信,使用定时任务来实现心跳检测等。