阿里云服务器免费领卷啦。

java短链接的简单实现

很久没更新了,加入了创业公司,从无到有的构建一套产品,从一开始的码框架到现在思考如何优化产品架构,适应更多的弹性需求和更大的数据量。时间真的是不够用,几乎快半年没有更新博客。近期产品慢慢走上正轨,又有小伙伴加入,所以抽出点时间总结一下这小半年内遇到的坑和走过的路。

说一说最近做的一个短链服务,短链服务其实很简单,其实就是一张表或者说是一个map:
+——-+———————–+
| 短链 | 长链 |
+——-+———————–+
| 7Y65s | https://www.google.com |
+——-+———————–+

就是这样一个结构,当用户访问 your-domain/7Y65s, 去表里查询一下对应的长链,301到该链接就可以了。

优化
基本的思路确定后,我们一点一点来优化。

首先分析大量查询肯定会出现在通过短链找长链这段逻辑中,如果用数据库肯定影响效率,缓存势在必行,而且一旦短链生成基本是不会变的,所以也不存在失效问题(这里可能会有个批量Archive的处理)。在我的项目中,我选择了redis作为缓存,反正是key-value的其他缓存组件肯定也能做。选用redis的原因是还可以用INCR来统计访问量。

redisTemplate.opsForHash().put("short-urls:" + slug, "long_url", url);
redisTemplate.opsForHash().increment("short-urls:" + slug, VISITS_FIELD, 1L);

查询这一侧做完,到了生成短链这一块,这里实际上是刚刚说的那张表的create操作。这里有个基本逻辑是:当一个长链还没有短链的时候,我们生成它并返回,如果已经存在,直接获取返回。

生成的算法直接贴代码:


package io.naza.urlshortener.generator;

import org.apache.commons.codec.digest.DigestUtils;

public class UrlShortHelper {

    private final static int LENGTH = 6;

    private static char[] DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();

    public static String[] shorten(String url) {
        String key = "SECRET"; // 自定义生成MD5加密字符串前的混合KEY
        String hex = DigestUtils.md5Hex(key + url);
        int hexLen = hex.length();
        int subHexLen = hexLen / 8;
        String[] shortStr = new String[subHexLen];

        for (int i = 0; i < subHexLen; i++) {
            StringBuilder outChars = new StringBuilder();
            int j = i + 1;
            String subHex = hex.substring(i * 8, j * 8);
            long idx = Long.valueOf("3FFFFFFF", 16) & Long.valueOf(subHex, 16);
            for (int k = 0; k < LENGTH; k++) { int index = (int) (Long.valueOf("0000003D", 16) & idx); outChars.append(DIGITS[index]); idx = idx >> 5;
            }
            shortStr[i] = outChars.toString();
        }
        return shortStr;
    }

}

项目中按照长链生成一个固定长度为6位的短链接,只要长链是一样的,那么每次生成的短链也一样。

考虑到每次生成短链前要查询一下长链是不是存在,继续加一个小缓存,这次反过来,长链作key,短链做value。

redisTemplate.opsForHash().put("short-urls", url, slug);

尾声
用比较简单的方式完成一个短链接服务,在做短链跳转的过程中可以分析用户的各类行为,比如操作系统,浏览器版本,地域等等。最后说两点要注意的:

redis毕竟是作为缓存使用的,建议数据还是要落一次在DB,比如在生成短链时,写入到DB一份。这样当redis挂了,还可以从DB中全量恢复。
对于长时间没有PV的短链,比如超过1年没有PV,需要做批量清理,一般一个月一次就可以了。

发表评论

要发表评论,您必须先登录