哈希算法题目:设计一个基于哈希的分布式短链生成与解析系统(支持高并发和防冲突)
字数 1860 2025-12-07 09:38:08

哈希算法题目:设计一个基于哈希的分布式短链生成与解析系统(支持高并发和防冲突)

题目描述
设计一个短链服务,能够将任意长URL(字符串)映射为一个全局唯一的、固定长度的短字符串(短链),并能通过短链快速解析回原始URL。系统需支持高并发的生成与查询请求,并确保不同URL映射到相同短链的概率(哈希冲突)极低。同时,需考虑短链的字符空间(如仅包含数字和字母)和长度限制(例如7位)。请给出核心算法与数据结构设计,并解释如何解决分布式环境下的并发与冲突问题。


解题过程

第一步:明确需求与约束

  1. 功能
    • generate(longUrl: str) -> str:输入长URL,返回短链(如 https://short.url/abc12De)。
    • resolve(shortKey: str) -> str:输入短链的键(如 abc12De),返回原始长URL,若不存在则返回空或错误。
  2. 核心要求
    • 短链键(如 abc12De)需全局唯一,且固定长度(如7位)。
    • 高并发下生成短链需高效且避免冲突。
    • 原始URL与短链键需双向可查。
  3. 字符集:假设使用 [0-9, a-z, A-Z],共62个字符。7位短键有 \(62^7 \approx 3.5 \times 10^{12}\) 种组合,足够避免短期内耗尽。

第二步:基础哈希映射设计
最简单的思路是使用哈希函数(如MD5、SHA-256)将长URL映射为固定长度的哈希值,再截取前若干位作为短键。例如:

  1. 计算 SHA256(longUrl),得到64位十六进制字符串。
  2. 取前28位(十六进制),每4位可编码为1个Base62字符(\(16^4=65536\) 种值映射到62个字符),得到7位短键。

问题

  • 不同URL可能哈希到相同短键(冲突)。
  • 直接截取会导致概率性冲突,需检测并处理。

第三步:解决冲突的策略

  1. 查询-重试机制
    • 生成短键后,先在全局存储(如分布式数据库)中查询该键是否已映射到其他URL。
    • 如果未使用,则存储 {短键: longUrl} 并返回。
    • 如果已使用,则给原URL添加随机后缀(如加时间戳或随机数)重新哈希,直到找到未使用的短键。
  2. 优化重试效率
    • 使用布隆过滤器预先判断短键是否可能被占用,减少数据库查询。
    • 对同一URL,可先检查是否已生成过短键(通过维护 {longUrl: 短键} 缓存)。

第四步:分布式唯一ID生成辅助
为彻底避免冲突,可将短键生成与哈希解耦:

  • 使用分布式唯一ID生成器(如雪花算法)产生全局唯一数字ID。
  • 将数字ID转换为Base62字符串作为短键。例如,ID 123456789 转换为 "8M0kX"(补足到7位)。
  • 优点:无需处理哈希冲突,ID本身唯一。
  • 存储映射:{短键: longUrl}{longUrl: 短键} 双表,支持双向查找。

第五步:具体步骤分解
生成短链流程

  1. 输入长URL,先查缓存(longUrl->短键),若存在则直接返回。
  2. 若不存在,用分布式ID生成器获取唯一整数ID。
  3. 将ID转换为Base62字符串,并填充或截断为固定长度(如7位)。
  4. 存储到数据库:
    • 主表:short_key (主键) -> long_url
    • 反向索引表:long_url_hash (对长URL做哈希索引) -> short_key
  5. 返回完整短链:https://short.url/{短键}

解析短链流程

  1. 从短链中提取短键(如从 https://short.url/abc12De 提取 "abc12De")。
  2. 用短键查询主表,得到原始URL。
  3. 若不存在,返回错误(如"404 Not Found")。

第六步:高并发与存储优化

  1. 数据库分片
    • 按短键的字符前缀或ID范围分片存储,分散读写压力。
  2. 缓存加速
    • 使用Redis缓存热点短键到URL的映射,提高解析速度。
  3. 防重复生成
    • 对同一长URL,用分布式锁(如基于Redis)确保并发下只生成一个短键。
  4. Base62转换算法示例
    BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    def to_base62(num: int, length=7) -> str:
        chars = []
        while num > 0:
            num, rem = divmod(num, 62)
            chars.append(BASE62[rem])
        # 反转并填充到固定长度
        result = ''.join(reversed(chars)).rjust(length, '0')
        return result[-length:]  # 确保长度精确
    

第七步:总结关键点

  • 核心思路:用分布式唯一ID替代哈希截取,避免冲突。
  • 存储:双映射表(短键→URL、URL哈希→短键)支持高效生成与解析。
  • 并发:结合分布式锁、缓存、数据库分片保证高可用。
  • 扩展:可添加TTL过期、访问统计、自定义短链等功能。

此设计在保证唯一性的同时,兼顾了分布式环境下的性能与可靠性。

哈希算法题目:设计一个基于哈希的分布式短链生成与解析系统(支持高并发和防冲突) 题目描述 设计一个短链服务,能够将任意长URL(字符串)映射为一个全局唯一的、固定长度的短字符串(短链),并能通过短链快速解析回原始URL。系统需支持高并发的生成与查询请求,并确保不同URL映射到相同短链的概率(哈希冲突)极低。同时,需考虑短链的字符空间(如仅包含数字和字母)和长度限制(例如7位)。请给出核心算法与数据结构设计,并解释如何解决分布式环境下的并发与冲突问题。 解题过程 第一步:明确需求与约束 功能 : generate(longUrl: str) -> str :输入长URL,返回短链(如 https://short.url/abc12De )。 resolve(shortKey: str) -> str :输入短链的键(如 abc12De ),返回原始长URL,若不存在则返回空或错误。 核心要求 : 短链键(如 abc12De )需全局唯一,且固定长度(如7位)。 高并发下生成短链需高效且避免冲突。 原始URL与短链键需双向可查。 字符集 :假设使用 [0-9, a-z, A-Z] ,共62个字符。7位短键有 \( 62^7 \approx 3.5 \times 10^{12} \) 种组合,足够避免短期内耗尽。 第二步:基础哈希映射设计 最简单的思路是使用哈希函数(如MD5、SHA-256)将长URL映射为固定长度的哈希值,再截取前若干位作为短键。例如: 计算 SHA256(longUrl) ,得到64位十六进制字符串。 取前28位(十六进制),每4位可编码为1个Base62字符(\(16^4=65536\) 种值映射到62个字符),得到7位短键。 问题 : 不同URL可能哈希到相同短键(冲突)。 直接截取会导致概率性冲突,需检测并处理。 第三步:解决冲突的策略 查询-重试机制 : 生成短键后,先在全局存储(如分布式数据库)中查询该键是否已映射到其他URL。 如果未使用,则存储 {短键: longUrl} 并返回。 如果已使用,则给原URL添加随机后缀(如加时间戳或随机数)重新哈希,直到找到未使用的短键。 优化重试效率 : 使用布隆过滤器预先判断短键是否可能被占用,减少数据库查询。 对同一URL,可先检查是否已生成过短键(通过维护 {longUrl: 短键} 缓存)。 第四步:分布式唯一ID生成辅助 为彻底避免冲突,可将短键生成与哈希解耦: 使用分布式唯一ID生成器(如雪花算法)产生全局唯一数字ID。 将数字ID转换为Base62字符串作为短键。例如,ID 123456789 转换为 "8M0kX" (补足到7位)。 优点:无需处理哈希冲突,ID本身唯一。 存储映射: {短键: longUrl} 和 {longUrl: 短键} 双表,支持双向查找。 第五步:具体步骤分解 生成短链流程 : 输入长URL,先查缓存( longUrl->短键 ),若存在则直接返回。 若不存在,用分布式ID生成器获取唯一整数ID。 将ID转换为Base62字符串,并填充或截断为固定长度(如7位)。 存储到数据库: 主表: short_key (主键) -> long_url 反向索引表: long_url_hash (对长URL做哈希索引) -> short_key 返回完整短链: https://short.url/{短键} 。 解析短链流程 : 从短链中提取短键(如从 https://short.url/abc12De 提取 "abc12De" )。 用短键查询主表,得到原始URL。 若不存在,返回错误(如"404 Not Found")。 第六步:高并发与存储优化 数据库分片 : 按短键的字符前缀或ID范围分片存储,分散读写压力。 缓存加速 : 使用Redis缓存热点短键到URL的映射,提高解析速度。 防重复生成 : 对同一长URL,用分布式锁(如基于Redis)确保并发下只生成一个短键。 Base62转换算法示例 : 第七步:总结关键点 核心思路:用分布式唯一ID替代哈希截取,避免冲突。 存储:双映射表(短键→URL、URL哈希→短键)支持高效生成与解析。 并发:结合分布式锁、缓存、数据库分片保证高可用。 扩展:可添加TTL过期、访问统计、自定义短链等功能。 此设计在保证唯一性的同时,兼顾了分布式环境下的性能与可靠性。