MST

星途 面试题库

面试题:Go WaitGroup在高可用分布式系统中的容错设计

在高可用的分布式系统中,部分节点可能会出现故障,导致正在执行的任务中断。假设你使用Go语言和WaitGroup来管理任务的并发执行,当某个节点故障时,如何确保系统能够继续运行,不丢失已完成部分的结果,并且重新分配未完成的任务?请详细阐述设计思路,并结合代码示例说明关键实现点。
15.6万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 任务划分:将整个任务划分成多个子任务,每个子任务可以独立执行。
  2. 节点监控:使用心跳机制或其他故障检测手段,实时监控每个节点的状态。
  3. 任务分配:将子任务分配到各个节点上执行。
  4. 结果收集:收集每个节点执行任务的结果。
  5. 故障处理:当检测到某个节点故障时,重新分配该节点上未完成的任务到其他正常节点上执行。

代码示例

package main

import (
    "fmt"
    "sync"
)

// 模拟任务执行函数
func executeTask(taskID int, resultChan chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    // 模拟任务执行
    result := taskID * 2
    resultChan <- result
}

func main() {
    const numTasks = 10
    const numNodes = 3
    var wg sync.WaitGroup
    resultChan := make(chan int, numTasks)
    tasks := make([]int, numTasks)
    for i := 0; i < numTasks; i++ {
        tasks[i] = i
    }

    // 初始化节点状态
    nodeStatus := make([]bool, numNodes)
    for i := range nodeStatus {
        nodeStatus[i] = true
    }

    // 模拟节点故障
    nodeStatus[1] = false

    for i := 0; i < numTasks; i++ {
        nodeIndex := i % numNodes
        if nodeStatus[nodeIndex] {
            wg.Add(1)
            go executeTask(tasks[i], resultChan, &wg)
        }
    }

    go func() {
        wg.Wait()
        close(resultChan)
    }()

    // 收集结果
    results := make([]int, 0, numTasks)
    for result := range resultChan {
        results = append(results, result)
    }

    // 重新分配未完成的任务
    for i := 0; i < numTasks; i++ {
        nodeIndex := i % numNodes
        if!nodeStatus[nodeIndex] {
            for j := 0; j < numNodes; j++ {
                if nodeStatus[j] {
                    wg.Add(1)
                    go executeTask(tasks[i], resultChan, &wg)
                    break
                }
            }
        }
    }

    go func() {
        wg.Wait()
        close(resultChan)
    }()

    // 再次收集结果
    for result := range resultChan {
        results = append(results, result)
    }

    fmt.Println("Final results:", results)
}

关键实现点

  1. 任务划分与分配:将任务划分成子任务,并根据节点状态分配到不同节点执行。
  2. 故障检测:通过修改nodeStatus数组模拟节点故障检测。
  3. 结果收集:使用chan来收集每个任务的执行结果。
  4. 任务重新分配:当检测到节点故障时,将未完成的任务重新分配到其他正常节点执行。
  5. WaitGroup:使用WaitGroup来等待所有任务执行完成,确保程序不会提前退出。