雪花算法相关面试题

雪花算法

Snowflake是一种分布式唯一ID生成算法,旨在解决分布式系统中唯一ID生成的需求。其ID结构如下:

  • 第一位:符号位,始终为0,因为Snowflake生成的是正数。

  • 41位时间戳:记录自定义的开始时间戳以来的毫秒数差值,支持约69年的时间戳。

  • 10位数据中心ID和工作机器ID:分别用来标识数据中心和机器,支持最多1024个数据中心和每个数据中心最多1024台机器。

  • 12位序列号:在同一毫秒内(同一台机器,同一时间戳)自增的计数器,支持每台机器每毫秒最多生成4096个唯一ID。

Snowflake算法的优点包括:

  1. 高效性:每秒能够生成大量唯一ID,测试显示可以达到约26万个ID。

  2. 唯一性:整个分布式系统内不会产生ID碰撞,由数据中心ID和机器ID作区分。

  3. 有序性:生成的ID按照时间自增排序,可以方便地根据ID的时间戳进行排序查询。

  4. 简单:算法相对简单,易于实现和部署。

Snowflake的核心在于使用时间戳、数据中心ID、机器ID和序列号的组合来保证生成的ID是唯一且有序的,适合于需要高性能、高可用且唯一标识的分布式系统场景。

Twitter_Snowflake SnowFlake的结构如下(每部分用-分开): 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000

  • 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0 41位时间截(毫秒级),注意,

  • 41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截) 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。

  • 41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69

  • 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId

  • 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号 加起来刚好64位,为一个Long型。 SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。

雪花算法时钟回拨问题

雪花算法强依赖时间戳,所以就会产生时钟回拨问题。也就是Linux服务器(系统)时间和真实时间不一致,可能会存在几秒的差异。就需要修改Linux时间,简单来说就是会出现取号问题。

通常可以用以下方式解决:

  • 异常处理,抛出异常,停止ID生成,但是这样就会暂停ID生成服务,也会影响系统的可用性。

  • 等待时间恢复,可以让线程睡眠等待,知道时间恢复。

  • 生成备用ID,比如随机数或者其他方式,但这种就需要增加额外的机制

  • 多时钟法,重新定个时钟,(可以拆分10位机器码,前几位作为不同时钟)

常用的分布式 ID 设计方案

首先,分布式全局 ID 的解决方案有很多,比如:

  • 使用 Mysql 的全局表

  • 使用 Zookeeper 的有序节点

  • 使用 MongoDB 的 objectid

  • redis 的自增 id

  • UUID 等等

这些方案只是解决基础的 id 唯一性问题,在实际生产环境中,需要构建一个全局唯一 id

还需要考虑更多的因素:

  • 有序性, 有序的 ID 能够更好地确认数据的位置,

以及 B+数据的存储结构中,范围查询的效率更高,并且可以提升 B+树数据维护的效率。

  • 安全性,避免恶意爬取数据造成数据泄露

  • 可用性,ID 生成系统的可用性要求非常高,一旦出现故障就会造成业务不可用的问题

  • 性能,全局 id 生成系统需要满足整个公司的业务需求,涉及亿级别的调用,对性能要求较高

因此,如果我们选择数据库的全局表,你每获取一次 id 就需要更新数据库,性能上限比较明显,

而且基于数据库构建高扩展和高性能的解决方案难度很大。

所以,目前市面上主流的解决方案是基于 Twitter 早期开源的 Snowflake 雪花算法(图片)。

它是由 64 位长度组成的全局 id 生成算法,通过对 64 位进行区间划分来表述不同含义实现唯一性

标识符一般不用,41位是系统毫秒级时间戳,10位工作机器ID,12位序列表示同毫秒内生成不同ID的能力。

它的好处是:

  • 算法实现简单

  • 不存在太多外部依赖

  • 可以生成有意义的有序编号

  • 基于位运算,性能也很好,Twitter 测试的生成ID峰值是 10 万个每秒。

另外,美团公司开源了一个全局唯一 id 生成系统 leaf,它里面也用到了雪花算法去构建全局唯一 id

并且在高性能和高可用方面,做了很多的优化,为美团内部业务提供了每天上亿次的调用。

雪花算法原理

雪花算法是一种生成分布式全局唯一 ID 的算法,它会得到一个 64 位长度的 long 类型数据。

其中这 64 位的数据,由 4 个部分组成

  • 第一个 bit 位是符号位,因为 id 不会是负数,所以它一般是 0

  • 接着用 41 个 bit 位来表示系统级毫秒单位的时间戳

  • 再用 10 个 bit 位来表示工作机器 id,保证不同服务器生成ID唯一性

  • 最后 12 个 bit 位表示递增的序列号来记录同毫秒内产生的不同 id

为什么MySQL分布式架构不能使用自增ID或者UUID做主键

为什么不能使用自增ID

在分布式系统下,使用自增ID,就会出现如下问题:

比如第一种情况,在不同库存放固定范围,1-10000,10000-20000,20000-30000,就只会先在第一个库存放,意味着一个时间段,生成的ID实际集中在一个库上,就起不到负载均衡,分担数据库压力的问题。第二种情况,将使用过的ID同步到其他库,这就需要加锁,非常损耗性能。第三种情况,每个库都自己维护自己的ID,这样查询时,ID就会重复不唯一。

使用UUID,全局唯一,当然可以当做主键,但是由于B+树是有序性,每次插入就会导致树的结构变化,为了维护树的有序性,就会导致数据量的迁移,也非常损耗性能。

所以比较雪花算法,具有全局唯一,实现简单,趋势递增,性能高等优势,注意雪花算法不是单调递增。

雪花算法是由一个 64 位长度的 long 类型数据组成。

其中这 64 位的数据,由 4 个部分组成

  • 第一个 bit 位是符号位,因为 id 不会是负数,所以它一般是 0

  • 接着用 41 个 bit 位来表示系统级毫秒单位的时间戳,可以表示69.7年左右,一般用时间差表示。

  • 再用 10 个 bit 位来表示工作机器 id,保证不同服务器生成ID唯一性

  • 最后 12 个 bit 位表示递增的序列号来记录同毫秒内产生的不同 id

雪花算法强依赖时间戳,所以就会产生时钟回拨问题。也就是Linux服务器(系统)时间和真实时间不一致,可能会存在几秒的差异。就需要修改Linux时间,简单来说就是会出现取号问题。

通常可以用以下方式解决:

  • 异常处理,抛出异常,停止ID生成,但是这样就会暂停ID生成服务,也会影响系统的可用性。

  • 等待时间恢复,可以让线程睡眠等待,知道时间恢复。

  • 生成备用ID,比如随机数或者其他方式,但这种就需要增加额外的机制

  • 多时钟法,重新定个时钟,(可以拆分10位机器码,前几位作为不同时钟)

<think>嗯,用户想了解华为OD的技术面试题。首先,我需要确认华为OD是什么。华为OD通常指的是华为的“Outstanding Developer”计划,也就是他们的人才招聘项目,主要面向软件开发、算法、测试等岗位的候选人。 接下来,用户需要的是技术面试题相关信息。作为面试准备,了解常见的题型和考察重点很重要。不过,华为的具体面试题可能受保密协议限制,不能公开详细题目。但可以整理一些常见的考点和题型,帮助用户进行准备。 首先,技术面试通常分为几个环节:在线测评、技术笔试、技术面试(可能有几轮)、综合面试等。每个环节考察的内容不同。用户可能更关注技术面试部分,尤其是编程题和系统设计题。 在技术面试中,常见的题型包括算法与数据结构、操作系统、网络、数据库、设计模式、项目经验等。对于华为OD来说,可能更侧重算法和编程能力,因为OD项目注重开发能力。 算法题方面,LeetCode中等难度的题目比较常见,比如动态规划、树、图、字符串处理等。例如,最长回文子串、二叉树的中序遍历、两数之和等题目。此外,可能涉及一些优化问题,比如时间复杂度或空间复杂度的优化。 系统设计题可能考察如何设计一个分布式系统、缓存机制、数据库分库分表等。这部分需要候选人具备一定的实际项目经验和系统架构能力。 此外,项目经验也是面试中的重要部分。面试官会询问候选人过去做过的项目,技术难点,解决方案,以及个人在项目中的贡献。需要准备好具体的案例,用STAR法则(情境、任务、行动、结果)来回答。 还有可能涉及计算机网络和操作系统的基础知识,比如TCP/IP协议栈、进程与线程的区别、内存管理、死锁等。数据库方面的事务隔离级别、索引原理等也是常考点。 另外,华为的企业文化也是面试中可能被考察的部分,比如对华为的了解、为什么选择华为等。虽然不属于技术问题,但提前准备会有帮助。 需要注意的是,华为OD的技术面试可能更注重实际编码能力和问题解决能力,因此在准备时要多练习手写代码,尤其是在白板或纸上写出无语法错误的代码。同时,注意代码的边界条件处理和异常情况处理。 总结下来,用户可能需要的是面试准备的方向和建议,而不是具体的题目。因此,回答时应重点介绍常见的考察领域、题型结构,以及备考策略,帮助用户系统地准备华为OD的技术面试。</think>华为OD(Outstanding Developer)技术面试通常分为多个环节,重点考察算法能力、编程基础、系统设计及项目经验。以下为面试准备的核心要点及常见题型解析: --- ### **一、面试流程概述** 1. **在线测评**:逻辑推理、性格测试、基础编码题。 2. **技术笔试**:3-4道编程题(中等难度,限时2小时)。 3. **技术面试(2-3轮)**:手撕代码 + 技术深度问答。 4. **综合面试**:项目经验、职业规划、软技能评估。 --- ### **二、技术面试高频考点** #### **1. 算法与数据结构** - **必考题型**: - **动态规划**:背包问题、最长子序列(例如:最长递增子序列)。 - **树与图**:二叉树遍历(非递归实现)、最近公共祖先(LCA)、拓扑排序。 - **字符串处理**:KMP算法、回文子串、字符串匹配。 - **数组与链表**:合并区间、链表反转、环检测。 - **例题**: ```text 输入一个整数数组,调整数组中数字的顺序,使所有奇数位于偶数前面,且保持奇数和偶数的相对顺序不变。 ``` **关键点**:双指针法或稳定排序思想。 #### **2. 操作系统** - **高频问题**: - 进程与线程的区别,协程的适用场景。 - 死锁的四个必要条件及避免策略。 - 虚拟内存与页面置换算法(如LRU实现)。 #### **3. 计算机网络** - **核心问题**: - TCP三次握手/四次挥手,TIME_WAIT状态的作用。 - HTTP与HTTPS的区别,SSL/TLS握手流程。 - 浏览器输入URL后发生了什么? #### **4. 数据库** - **重点考察**: - 事务的ACID特性,隔离级别及脏读/幻读问题。 - B+树索引原理,联合索引的最左匹配原则。 - SQL优化:EXPLAIN命令解析执行计划。 --- ### **三、手撕代码环节技巧** 1. **代码规范**: - 变量命名清晰,避免全局变量。 - 边界条件处理(如空输入、负数、溢出)。 2. **复杂度分析**: - 主动说明时间/空间复杂度,提出优化思路。 - 示例:两数之和问题,从$$O(n^2)$$暴力法优化到$$O(n)$$哈希表。 --- ### **四、系统设计题示例** **题目**:设计一个分布式ID生成器(要求高可用、全局唯一、趋势递增)。 **回答框架**: 1. **需求分析**:唯一性、性能、容灾。 2. **方案选型**: - 雪花算法(Snowflake):$$ \text{ID} = \text{时间戳} + \text{机器ID} + \text{序列号} $$。 - Redis原子操作INCR。 3. **容错设计**:机器ID动态分配、时钟回拨处理。 --- ### **五、项目经验提问** - **STAR法则**: - **Situation**:项目背景与目标。 - **Task**:你的具体职责。 - **Action**:技术选型与难点突破。 - **Result**:量化成果(如性能提升30%)。 --- ### **六、备考建议** 1. **刷题平台**:LeetCode(精选华为题库)、牛客网。 2. **模拟面试**:使用白板练习手写代码,录音复盘表达逻辑。 3. **技术深度**:深入理解1-2个技术栈(如Redis源码、JVM原理)。 --- 通过系统性准备算法、底层原理及项目表述,可显著提升通过率。建议每天至少完成3道中等难度算法题,并针对薄弱领域专项突破。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值