如何用Redis设计一个高性能短链接生成服务?

来源:网络学院作者:深圳网站建设头衔:草根站长
导读:本期聚焦于深圳网站建设创作的《如何用Redis设计一个高性能短链接生成服务?》,敬请观看详情。短链接服务的核心难点在于如何把长网址映射成唯一的短码,并且在高并发场景下快速完成跳转。本文围绕Redis展开,介绍自增ID加62进制编码、哈希算法加布隆过滤器、号段预分配这几种常见方案的实现原理与代码示例,分析各自的优缺点,并给出缓存穿透防护、跳转301与302的选择、过期清理策略等落地细节,帮助你搭建一套既节省内存又能扛住大流量的短链接系统。

短链接服务看似简单,无非是把一个长网址换成短码再跳转回去,但真正要做成一个扛得住大流量的服务,方案选型和细节处理都有讲究。核心问题只有两个:一是如何生成不重复的短码,二是如何在跳转时以极低的延迟查到对应的长网址。Redis凭借原子的自增操作和亚毫秒级的读写性能,恰好能同时解决这两个问题。本文从短码生成方案讲起,逐步展开存储设计、跳转优化和运维细节。

如何用Redis设计一个高性能短链接生成服务?

短码生成的三种主流方案对比

生成短码的思路主要有三种:自增ID转换进制、对长网址做哈希、以及号段预分配。三者的差别体现在唯一性保障、短码长度和实现复杂度上,需要根据业务量级来选择。

第一种是自增ID加62进制编码。利用Redis的INCR命令拿到一个全局递增的数字,再把数字转成由数字、大小写字母组成的62进制字符串。62的7次方约等于3.5万亿,也就是说7个字符的短码足够支撑绝大多数业务。这种方案的唯一性由INCR的原子性天然保证,不需要额外去重,是最省心的做法。缺点是短码是连续的,存在被恶意遍历的风险,可以在编码前对ID做一次可逆混淆,比如按固定规则打乱位序。

第二种是哈希算法方案。对长网址做MD5或MurmurHash计算,取其中若干位作为短码。优点是同一个长网址会得到相同的短码,天然去重。但哈希存在碰撞可能,需要配合Redis的SETNX命令判断该短码是否已被占用,碰撞后重算。如果业务里大量网址需要查重,还可以引入布隆过滤器先快速筛掉绝大部分重复请求,降低Redis压力。

第三种是号段预分配。应用服务器不每次都去请求Redis,而是一次性取走一段ID(比如1000个)缓存在本地内存中使用,用完再取下一段。这样把网络交互摊薄到千分之一,Redis的QPS压力大幅下降,适合创建短链的并发特别高的场景。代价是应用重启会浪费一小段未用完的号,好在号段本身成本极低。

基于自增ID方案的完整实现

综合来看,自增ID加62进制是最均衡的选择,下面给出关键实现。先定义62个字符的编码表,然后实现数字转62进制的函数:

import redis

# 62进制字符表
CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
BASE = len(CHARS)

def encode_base62(num):
    """将自增数字编码为62进制短码"""
    if num == 0:
        return CHARS[0]
    result = []
    while num > 0:
        num, remainder = divmod(num, BASE)
        result.append(CHARS[remainder])
    return ''.join(reversed(result))

def obfuscate(num):
    """对ID做简单可逆混淆,避免短码连续可猜测"""
    return (num * 1103515245 + 12345) % (2 ** 61 - 1)

def create_short_url(r, long_url):
    # INCR是原子操作,并发下不会重复
    seq = r.incr("short:url:counter")
    code = encode_base62(obfuscate(seq))
    # 用Hash存储映射,方便后续附加统计字段
    r.hset(f"short:{code}", mapping={
        "long_url": long_url,
        "created_at": int(time.time())
    })
    return code

存储结构上建议使用Hash而不是简单的String。String只能存长网址本身,而Hash可以在同一个key下附加创建时间、点击计数、过期时间等字段,后续做统计功能时不用改结构。短码到长网址的映射设置合理的过期时间也很重要,冷数据长期占用内存不划算,可以利用Redis的惰性删除配合定时任务做二次清理。

跳转链路的性能优化

跳转是这个服务里读压力最大的环节,一次跳转的本质就是一次GET short:code。优化读性能有几个层次可以叠加。

第一层是本地缓存。热门短链接的访问往往符合二八定律,在应用层加一个LRU本地缓存(比如容量10万条),命中时连Redis都不用访问,响应时间可以压到微秒级。本地缓存和Redis之间用短过期时间(例如60秒)保持最终一致性,即使短链被修改也能快速生效。

第二层是防穿透保护。恶意用户可能会拿不存在的短码疯狂请求,每次都打到Redis。解决办法是把“短码不存在”这个结果也缓存起来,写入一个特殊占位值并设置短TTL;或者在查询前用布隆过滤器拦截,不存在的短码直接返回404,一个几MB内存的布隆过滤器就能覆盖亿级短码的判重需求。

第三层是跳转方式的选择。301是永久重定向,浏览器会缓存结果,后续请求不再到达服务器,省流量但会丢失点击统计;302是临时重定向,每次请求都会回源,能记录访问日志。做营销分析类的短链服务通常选302,纯粹省带宽的场景选301。无论哪种,都要在响应头里带上Cache-Control控制浏览器行为,避免被无脑缓存。

// Java跳转伪代码示意
public String resolve(String code) {
    String key = "short:" + code;
    // 先查本地缓存
    String longUrl = localCache.getIfPresent(key);
    if (longUrl != null) {
        return longUrl;
    }
    // 再查Redis
    Map<Object, Object> fields = redisTemplate.opsForHash().entries(key);
    if (fields.isEmpty()) {
        // 缓存空值防止穿透
        localCache.put(key, EMPTY_PLACEHOLDER);
        return null;
    }
    longUrl = (String) fields.get("long_url");
    localCache.put(key, longUrl);
    return longUrl;
}

高可用与容量规划

单点Redis一旦宕机,整个短链服务就不可用,因此生产环境至少要做主从加哨兵的部署。由于这个场景读多写少的特征非常明显,可以配置多个从节点分担读流量,主节点只负责INCR写操作。进一步还可以按短码首字母做分片,把不同前缀的key路由到不同Redis实例,容量和吞吐都能水平扩展。

内存方面可以粗略估算:一条短链映射包含短码、长网址和元数据,按平均500字节算,一亿条数据约50GB。如果长网址普遍较长,可以考虑对长网址做压缩存储,或者把冷数据下沉到MySQL,Redis只保留热点部分,通过访问时回源加载的方式维持一致性。回源操作要用SETNX加锁防止并发回源造成数据库压力突增。

最后别忘了监控。INCR的速率直接反映短链创建量,缓存命中率反映读链路健康度,Redis的内存碎片率和慢查询日志要定期查看。把这几个指标接入告警,短链接服务就能长期稳定运行了。

Redis短链接生成发号器修改时间:2026-09-16 01:30:33

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0916/57627.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。