短链服务设计

资料参考地址1: 系统设计之路:如何设计一个URL短链服务

资料参考地址2:分布式系统设计-短连接服务设计

一 什么是 URL 短链

URL 短链,就是把原来较长的网址,转换成比较短的网址。

image-20230918235129695

好处是

  • 网址短、美观、便于发布、传播,可以写更多有意义的文字;
  • 我们平常看到的二维码,本质上也是一串 URL ,如果是长链,对应的二维码会密密麻麻,扫码的时候机器很难识别,而短链则不存在这个问题;
  • 出于安全考虑,不想让有意图的人看到原始网址

二 短链跳转主要原理

重定向

客户端(或浏览器)请求短链: https://j.mp/38Zx5XC

短链服务器收到请求后,返回 status code: 301 或 302 ,说明需要跳转,同时也通过 location 字段告知客户端:你要访问的其实是下面这个长网址 :
https://activity.icoolread.com/act7/212/duanxin/index

客户端收到短链服务器的应答后,再去访问长网址:
https://activity.icoolread.com/

[image-20230918235354354

短链接跳转的示例代码

好的,以下是一个使用 Spring Boot 实现短链接跳转的示例代码,通过返回 301 或 302 状态码并设置 Location 头来实现跳转。

在 ShortUrlController 类:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ShortUrlController {
    // 这里简单模拟一个短链接到长链接的映射关系,实际应用中可以使用数据库存储
    private static final String SHORT_URL_TO_LONG_URL_MAP = "https://example.com/long-url";

    @GetMapping("/short/{shortUrlId}")
    public ResponseEntity<Void> redirectToLongUrl(@PathVariable String shortUrlId) {
        // 这里假设 shortUrlId 是唯一标识,根据实际情况获取对应的长链接
        String longUrl = SHORT_URL_TO_LONG_URL_MAP;

        // 返回 302 临时重定向,也可以根据需求改为 301 永久重定向
        return ResponseEntity.status(HttpStatus.FOUND).header("Location", longUrl).build();
    }
}

三 设计短链服务要考虑的点

  • 高可用-搭集群-负载均衡
  • 读流量大时考虑缓存
  • 数据量大时考虑分库分表以及过期清除

四 生成短链的示例代码

将长链接经过MurmurHash算法生成整数,然后将整数转换为Base62字符

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.1-jre</version> 
</dependency>
import com.google.common.hash.Hashing;
import java.nio.charset.StandardCharsets;
import org.apache.commons.codec.binary.Base64;

public class UrlShortenerDemo {
    public static void main(String[] args) {
        String longUrl = "https://www.example.com"; // 要缩短的长链接

        // 使用MurmurHash算法生成整数
        int murmurHash = Hashing.murmur3_32().hashString(longUrl, StandardCharsets.UTF_8).asInt();

        // 将生成的整数转化为Base62的字符
        String base62 = encodeBase62(murmurHash);

        System.out.println("Long URL: " + longUrl);
        System.out.println("MurmurHash: " + murmurHash);
        System.out.println("Short URL (Base62): " + base62);
    }

    // 使用Base62编码将整数转化为字符串
    private static String encodeBase62(int num) {
        String characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        StringBuilder result = new StringBuilder();

        while (num > 0) {
            int remainder = num % 62;
            result.insert(0, characters.charAt(remainder));
            num /= 62;
        }

        return result.toString();
    }
}

五 短链为什么要设置过期

1.安全性:如果短链永久有效,那么一旦短链泄露或者被滥用,长链接将永远处于风险之中。过期机制可以降低这种风险,因为即使短链被泄露,只要短链已过期,长链接将不再可用。

2.资源管理:短链服务需要存储大量的短链接映射,如果不实行过期机制,数据库会不断增长,导致资源浪费。过期机制可以自动删除不再需要的短链接映射,释放资源。

3.促使用户行动:短链的过期时间可以用来促使用户尽快点击链接,例如,在市场推广中,您可以创建一个短链,仅在活动期间有效,这样可以增加用户点击的紧迫感。

要实现短链的过期功能,可以考虑以下步骤:

  1. 数据库表设计:在短链接的数据库表中添加一个过期时间字段(expiration_date),用于存储短链的过期日期和时间。

    CREATE TABLE url_mapping (
     id INT AUTO_INCREMENT PRIMARY KEY,
     long_url VARCHAR(255) NOT NULL,
     short_url VARCHAR(50) NOT NULL,
     created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     expiration_date TIMESTAMP
    );
    
  2. 生成短链时设置过期时间:在生成短链接时,为其设置一个过期时间,可以是从当前时间开始的一段时间后,或者是一个具体的未来日期和时间。这可以在业务逻辑中实现。

    public String shortenUrl(String longUrl, LocalDateTime expirationDate) {
     String shortUrl = generateShortUrl();
     UrlMapping urlMapping = new UrlMapping();
     urlMapping.setLongUrl(longUrl);
     urlMapping.setShortUrl(shortUrl);
     urlMapping.setExpirationDate(expirationDate);
     urlMappingRepository.save(urlMapping);
     return BASE_URL + shortUrl;
    }
    
  3. 验证短链是否过期:在访问短链接时,首先验证当前时间是否在过期时间之前。如果短链已过期,可以采取适当的措施,例如返回一个过期提示或重定向到其他页面。

    public String expandUrl(String shortUrl) {
     UrlMapping urlMapping = urlMappingRepository.findByShortUrl(shortUrl);
     if (urlMapping != null) {
         LocalDateTime expirationDate = urlMapping.getExpirationDate();
         if (expirationDate == null || expirationDate.isAfter(LocalDateTime.now())) {
             return urlMapping.getLongUrl();
         } else {
             // 短链已过期,采取适当的处理
             return "Short URL has expired";
         }
     }
     return "Short URL not found";
    }
    

通过这种方式,您可以实现短链接的过期功能,确保链接在指定的时间后不再可用。请注意,过期功能的具体实现方式可以根据需求进行调整,例如,您可以使用定时任务来定期清理过期链接,或者将过期链接移动到归档表中,以减小数据库大小。

六 布隆式过滤器防重复

可用redisson的实现布隆过滤器

防重复流程

先通过布隆过滤器进行快速初步判断,如果布隆过滤器显示不存在,直接插入数据库可以减少不必要的数据库查询,提高效率。若布隆过滤器显示存在,再到数据库精准查询,能确保准确性,避免误判导致的重复插入。

为什么这么做

这种方式能避免对数据库的过多访问,因为布隆过滤器可以在内存中快速进行判断,拦截大部分明显不存在的短链,只有在可能存在重复的情况下才去查询数据库。同时,通过布隆过滤器和数据库的双重验证,能有效保证短链的唯一性。

七 实际使用场景

做裂变引流时,我们服务采用短链加二维码的方式

原因有这几点:

一是美观,长链接杂乱、复杂二维码看起来不精致,换成短链与简洁二维码,视觉上更清爽,能提升用户参与意愿。

二是时效管控,短链可设置有效期,给用户紧迫感,督促他们赶紧分享,加速裂变传播。

三是数据安全,短链能隐藏真实接口,防止数据被篡改,保障业务数据可靠。

四是数据追踪,通过短链能精准记录用户操作,了解行为、来源等信息,方便后续优化营销策略。

另外,关于能否在微信分享,答案是可以,只要把短链域名加入微信白名单就行,这样就能利用微信平台做好裂变引流。

posted @   进击的小蔡鸟  阅读(284)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示