美文网首页@IT·互联网
短链接生成算法

短链接生成算法

作者: liukeless | 来源:发表于2024-05-16 14:58 被阅读0次

短链接生成

业务需求中经常会出现在短信中发送链接信息,存在一些链接长度太长,导致短信发送失败。 另外短信服务商收费是根据短信内容收费,链接越长短信收费也就越多; 所以短链接服务就很重要 ,需要把业务的长地址链接映射成短链接; 客户访问短链接时再重定向到原始的长链接来达成要求;

下面是java实现的端链接算法

import org.apache.commons.codec.binary.Hex;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.UUID;

public class ShortLinkGenerator {

    /**
     * 所有字符集, url安全字符,不会被转义
     */
    private static final char[] CHARS = new char[]{
            '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',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
    };

    /**
     * 字符集长度,多进制表示
     */
    private static final int BASE = CHARS.length;
    /**
     * 生产短链接的长度
     */
    private static final int SHORT_LINK_LENGTH = 8;

    /**
     * hash冲突是声随机生成salt的长度
     */
    private static final int SALT_LENGTH = 6;

    /**
     * 随机数生成器
     */
    private static final SecureRandom random = new SecureRandom();

    /**
     * 生成随机盐
     *
     * @return
     */
    public static String generateSalt() {
        StringBuilder salt = new StringBuilder(SALT_LENGTH);
        for (int i = 0; i < SALT_LENGTH; i++) {
            int index = random.nextInt(CHARS.length);
            salt.append(CHARS[index]);
        }
        return salt.toString();
    }

    /**
     * 生成短链接
     *
     * @param url
     * @return
     */
    private static String generateShortLink(String url) {
        try {
            // 使用SHA-256哈希函数
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = digest.digest(url.getBytes());

            // 将哈希值转换为多进制字符串
            String baseStr = hashToBaseMulti(hashBytes);

            // 确保字符串长度为8位
            return baseStr.substring(0, SHORT_LINK_LENGTH);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-256 algorithm not found", e);
        }
    }

    /**
     * 生成短链接,加盐的方式
     *
     * @param url
     * @param salt
     * @return
     */
    private static String generateShortLinkWithSalt(String url, String salt) {
        try {
            url = url + salt;
            // 使用SHA-256哈希函数
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = digest.digest(url.getBytes());

            // 将哈希值转换为进制字符串
            String baseStr = hashToBaseMulti(hashBytes);

            // 确保字符串长度为8位
            return baseStr.substring(0, SHORT_LINK_LENGTH);
        } catch (Exception e) {
            throw new RuntimeException("生成短链接异常", e);
        }
    }

    /**
     * 将哈希值转换为多进制字符串
     *
     * @param hashBytes
     * @return
     */
    private static String hashToBaseMulti(byte[] hashBytes) {
        // 使用BigInteger来避免负数问题
        BigInteger num = new BigInteger(1, hashBytes);
        StringBuilder baseStr = new StringBuilder();

        if (num.compareTo(BigInteger.ZERO) <= 0) {
            // 出现负数 直接用sha256的值, 测试未出现负数情况
            String str = Hex.encodeHexString(hashBytes);
            num = null;
            return str;
        }

        // 将大整数转换为多进制
        while (num.compareTo(BigInteger.ZERO) > 0) {
            BigInteger[] divRem = num.divideAndRemainder(BigInteger.valueOf(BASE));
            baseStr.append(CHARS[divRem[1].intValue()]);
            num = divRem[0];
        }

        // 如果生成的字符串长度不足8位,进行填充
        while (baseStr.length() < SHORT_LINK_LENGTH) {
            // 重复
            baseStr.append(baseStr);
        }
        num = null;
        // 由于上面是从低位到高位,需要反转
        return baseStr.reverse().toString();
    }

    public static long reverseBaseToDecimal(String input) {
        long result = 0;
        int power = input.length() - 1;
        for (char c : input.toCharArray()) {
            int index = getIndex(c);
            result += index * Math.pow(BASE, power);
            power--;
        }
        return result;
    }

    public static int getIndex(char c) {
        for (int i = 0; i < CHARS.length; i++) {
            if (CHARS[i] == c) {
                return i;
            }
        }
        throw new IllegalArgumentException("Invalid character: " + c);
    }

    public static void main(String[] args) {
        String s = generateShortLink("1");
        while (true) {
            System.out.println(generateShortLink(UUID.randomUUID().toString()));
        }
    }
}

测试输出

vGGAjErZ
Su2eWLuo
KyZ2J3P1
ikq0oQpy
d9ghFeU5
Yylh3Buu
DLqpzq9K
xdyDTG1h
exGAIWmF
iA8oPHY3
gkX9L96F
OvtVYSuc
ln5NkrOw
5FzvMOzT
vp3TfKqq
gVFcHevY
dVIKizG3
YlMv3Msx
ryHOLnaH
6awUTwj6
pwe2uBGx
5Moa9BME
HnNMpjUn
IIkBICM5
V6mMA03m
hpeNuGzl
LWsNzL9U
y1yKfmKR
7T9kdcdg
ZzsrKlCm

最终实测 hash碰撞率 千万分之三, 性能17w/s , 能满足常规业务要求

以上仅为算法实现,如完整短链服务,还需要处理hash冲突情况;

相关文章

  • 短链接生成算法(乱序)

    最近公司的项目中需要实现一个防伪查询系统,当时一听到这个任务我就自然而然的想到长连接生成短链接这个系统.然后就习惯...

  • 短链接/短网址生成算法

    参考文章两种JAVA实现短网址服务算法JAVA实现-URL短网址生成算法【原创】这可能是东半球最接地气的短链接系统设计

  • StanFord 机器学习公开课笔记(4):生成学习算法

    本讲视频及讲义链接 生成学习算法 生成学习算法和判别学习算法的区别 判别学习算法(Discriminative) ...

  • 短链接生成

    在平常开发中可能会遇到url过长的情况,一大堆参数都在后面跟着将url变得很糟看着也很混乱,于是出现了短连接,可以...

  • php 生成短链接

    根据需求 - 选择自己生成短域名还是利用第三方api获得 自己生成短链接 注意:中心思想"域名转发"既然是域名转发...

  • nodejs生成短链接

    应用场景:发短信的时候,可能由于参数的问题导致链接过长,超出短信字数限制,所以链接需要越短越好 原理 生成一个唯一...

  • todo

    短链接生成. 秒杀系统 短链接生成 高并发的红包系统 分布式ID生成 分布式限流 分布式定时任务 新浪微博怎么推送...

  • Mysql分库分表实践(短链接的实现)

    业务场景 简单分析一下短链接的业务场景。参照百度短链接http://dwz.cn/ 。 根据长链接生成一个短链接。...

  • (极客时间)短 URL 生成器设计

    一、需求设计一个短URL生成器(Fuxi)短 URL 生成器,也称作短链接生成器,就是将一个比较长的 URL 生成...

  • 测试短链接生成

    一杯二锅头 好汉不回头 你说要走!你走就走! 获取授权

网友评论

    本文标题:短链接生成算法

    本文链接:https://www.haomeiwen.com/subject/bmabfjtx.html