MST

星途 面试题库

面试题:Go生成器扩展与边界处理之专家题

在分布式系统场景下,有一个基于Go语言的生成器负责生成唯一ID。现在需要对该生成器进行扩展,使其能够适应多节点并发生成ID的需求,并且保证生成的ID全局唯一且无冲突。请详细阐述设计思路,包括如何处理网络延迟、节点故障等边界情况,同时给出核心部分的代码示例及对整体架构的描述。
20.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. ID生成算法选择
    • 常用的分布式ID生成算法如雪花算法(Snowflake)。雪花算法生成的ID由时间戳、机器ID、序列号三部分组成。时间戳保证了ID的大致递增顺序,机器ID确保不同节点生成的ID不同,序列号用于在同一毫秒内不同请求生成不同ID。
  2. 处理网络延迟
    • 由于不同节点时钟可能存在偏差,为避免因时钟回退导致ID冲突,节点启动时获取NTP(网络时间协议)服务器时间进行时钟同步。
    • 若检测到时钟回退,等待时钟追上前一个时间戳后再继续生成ID。
  3. 处理节点故障
    • 为了保证即使某个节点故障,整个系统仍能正常生成ID,每个节点生成的ID应尽量独立,不依赖其他节点。
    • 可以设置备用节点,当主节点故障时,备用节点接管ID生成任务。同时,记录故障节点的ID生成状态(如时间戳、序列号),在故障节点恢复后,从记录的状态继续生成ID,避免重复。

核心代码示例(基于雪花算法)

package main

import (
    "errors"
    "fmt"
    "sync"
    "time"
)

// Snowflake结构体定义
type Snowflake struct {
    machineID  int64
    datacenterID int64
    sequence   int64
    lastStamp  int64
    mutex      sync.Mutex
}

// NewSnowflake创建一个新的Snowflake实例
func NewSnowflake(machineID, datacenterID int64) (*Snowflake, error) {
    if machineID < 0 || machineID > 1023 {
        return nil, errors.New("machine ID can't be greater than 1023 or less than 0")
    }
    if datacenterID < 0 || datacenterID > 1023 {
        return nil, errors.New("datacenter ID can't be greater than 1023 or less than 0")
    }
    return &Snowflake{
        machineID:  machineID,
        datacenterID: datacenterID,
        sequence:   0,
        lastStamp:  -1,
    }, nil
}

// Generate生成唯一ID
func (s *Snowflake) Generate() int64 {
    s.mutex.Lock()
    defer s.mutex.Unlock()

    now := time.Now().UnixNano() / 1000000

    if now < s.lastStamp {
        // 时钟回退处理
        now = s.lastStamp
    }

    if now == s.lastStamp {
        s.sequence = (s.sequence + 1) & 4095
        if s.sequence == 0 {
            // 等待下一毫秒
            for now <= s.lastStamp {
                now = time.Now().UnixNano() / 1000000
            }
        }
    } else {
        s.sequence = 0
    }

    s.lastStamp = now

    return (now << 22) |
        (s.datacenterID << 12) |
        (s.machineID << 12) |
        s.sequence
}

整体架构描述

  1. 节点层:每个分布式节点都运行一个雪花算法的实例,负责在本地生成唯一ID。每个节点通过配置获取自己的机器ID和数据中心ID。
  2. 时钟同步层:通过NTP协议与时间服务器同步时钟,确保各个节点的时间偏差在可接受范围内。
  3. 监控与故障处理层:有一个监控系统负责监测各个节点的运行状态。当某个节点故障时,监控系统将故障信息通知给备用节点,备用节点接管ID生成任务。同时,故障节点恢复后,监控系统协助其恢复到故障前的ID生成状态。