用Redis实现长链转短链

2022-05-05 17:04:04 浏览数 (1)

问题引出

在生活中有很多场景需要把长链接转化为短连接,比如微博限制字数为140字一条,那么如果我们需要发一些链接上去,但是这个链接非常的长,以至于将近要占用我们内容的一半篇幅,这肯定是不能被允许的,所以短链接应运而生了。

又比如短信的链接都是处理后的短链接,如果链接很长,也会影响短信的阅读体验。

实际是长链接

代码实现

这里我们采用Redis存储短链接。

我们先来定义几个常量

代码语言:javascript复制
private static final String SHORT_URL_KEY = "SHORT_URL_KEY";
private static final String LOCALHOST = "http://t.cn/";
private static final String SHORT_LONG_PREFIX = "short_long_prefix_";
private static final String CACHE_KEY_PREFIX = "cache_key_prefix_";
private static final int CACHE_SECONDS = 1 * 60 * 60;

final static char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
        '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
        'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'v', 'W', 'x', 'Y',
        'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
        'o', 'p', 'q', 'r', 's', 't', 'u', 'V', 'w', 'X', 'y', 'Z'
};

SHORT_URL_KEY是短链末尾的值。LOCALHOST是短链的前缀。

「从Redis里获取短链接」

代码语言:javascript复制
public String getShortUrl(String longUrl, Decimal decimal) {
    String cache = redisTemplate.opsForValue().get(CACHE_KEY_PREFIX   longUrl);
    if (cache != null) {
        log.info("从缓存【{}】中获取到:{}",CACHE_KEY_PREFIX   longUrl,cache);
        return LOCALHOST   toOtherBaseString(Long.valueOf(cache), decimal.x);
    }

    Long num = redisTemplate.opsForValue().increment(SHORT_URL_KEY);
    redisTemplate.opsForValue().set(SHORT_LONG_PREFIX   num, longUrl);

    redisTemplate.opsForValue().set(CACHE_KEY_PREFIX   longUrl, String.valueOf(num), CACHE_SECONDS, TimeUnit.SECONDS);
    return LOCALHOST   toOtherBaseString(num, decimal.x);
}

num通过「Redis」的原子自增获取,每生成一个链接这里就加1。

「转码方式」

代码语言:javascript复制
private String toOtherBaseString(long n, int base) {
    long num = 0;
    if (n < 0) {
        num = ((long) 2 * 0x7fffffff)   n   2;
    } else {
        num = n;
    }
    char[] buf = new char[32];
    int charPos = 32;
    while ((num / base) > 0) {
        buf[--charPos] = digits[(int) (num % base)];
        num /= base;
    }
    buf[--charPos] = digits[(int) (num % base)];
    return new String(buf, charPos, (32 - charPos));
}

将10进制转换成其他进制。我们来对这个方法做个测试。

代码语言:javascript复制
@Test
public void testToString() {
    int n = 568002355;
    int base = 64;
    String s = toOtherBaseString(n, base);
    System.out.println(s);

}

「测试」

代码语言:javascript复制
@Test
public void testShortUrl() {
    String url = "www.google.com";

    String shortUrl = shortUrlUtil.getShortUrl(url, ShortUrlUtil.Decimal.D64);
    System.out.println("短链:"   shortUrl);
}

我们将www.google.com转化为短链接

转成的短链接如图所示

代码语言:javascript复制
短链:http://t.cn/4

SHORT_URL_KEY的值为4,代表短链末尾的值为4。

而对应长链存储在这里。

这样同一长链每次生成的短链是一样的。

再运行一次,显示的短链还是一样。

采用Redis原子自增生成短链,即使是在分布式环境下也不会重复。利用Redis生成在高并发下也会有很好的性能。

0 人点赞