java短网址服务(TinyURL)生成算法

前不久做了一个优惠劵的分享功能,其中一个功能就是生成一个优惠劵分享短链接。生成的短链接要求每个链接都是唯一的,并且长度尽可能短。在网上查了一下相关的思路,发现了一个不错的算法。这个算法的思路就是用[a-zA-Z0-9]建立一个长度为62的矩阵,然后把矩阵打乱,再生成一个全局唯一的数字,再把这个数字用矩阵内的元素表示转换成62进制,生成的链接长度最大才11位。所以短链接的生成关键点就变成了如何生成一个全局唯一的数字和实现进制的转换。

1、生成全局唯一的数字

这本质是一个分布式ID的问题。如果简单处理的话可以借用redis的incr操作这样每次取到的ID都是单调递增且唯一的。另外一种方式是借用mysql,这里不是借用mysql的主键的auto_incr特性。而是每一台应用来请求时分配一个范围比如 s1 [100-200], s2 来请求的时候就分配 [201-301],本质是利用乐观锁进行一个cas操作。

如果不想借助外部去生成ID的话,可以用UUID算法。UUID长度12个字节组成由,以下几个部分组成。

  • 4个字节表示的Unix timestamp,
  • 3个字节表示的机器的ID
  • 2个字节表示的进程ID
  • 3个字节表示的计数器

UUID是一类算法的统称,具体有不同的实现。优点是每台机器可以独立产生ID,理论上保证不会重复,所以天然是分布式的,缺点是生成的ID太长,不仅占用内存,而且索引查询效率低。

还有一个叫Twitter Snowflake算法,本质上看起来与UUID有些类似。

总的来说redis,mysql解决方案就比较简单直接可以满足大部分的场景,如果要保证高性能和高可用的话UUID和Twitter Snowflake算法就更合适,实现起来相对复杂一些。

2、进制转换

这个操作就相对简单了。直接上代码:

/**
 * 短链接生成
 */
public class TinyURL {

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

  public static Map<Character, Integer> charValueMap = new HashMap<Character, Integer>();

  //初始化map
  static {
    for (int i = 0; i < array.length; i++) charValueMap.put(array[i], i);
  }

  public static void main(String[] args) {
    for (int i = 0; i < 100; i++) {
      long number = Long.MAX_VALUE - i;
      String decimalStr = numberConvertToDecimal(number, 62);
      System.out.println(number + " 转换成 " + decimalStr);
      long toNumber = decimalConvertToNumber(decimalStr, 62);
      System.out.println(decimalStr + " 转换成 " + toNumber);
    }
  }

  /**
   * 把数字转换成相对应的进制,目前支持(2-62)进制
   *
   * @param number
   * @param decimal
   * @return
   */
  public static String numberConvertToDecimal(long number, int decimal) {
    StringBuilder builder = new StringBuilder();
    while (number != 0) {
      builder.append(array[(int) (number - (number / decimal) * decimal)]);
      number /= decimal;
    }
    return builder.reverse().toString();
  }

  /**
   * 把进制字符串转换成相应的数字
   * @param decimalStr
   * @param decimal
   * @return
   */
  public static long decimalConvertToNumber(String decimalStr, int decimal) {
    long sum = 0;
    long multiple = 1;
    char[] chars = decimalStr.toCharArray();
    for (int i = chars.length - 1; i >= 0; i--) {
      char c = chars[i];
      sum += charValueMap.get(c) * multiple;
      multiple *= decimal;
    }
    return sum;
  }

}

这里面有个小优化就是用charValueMap记录每个字符对应的数值,这是一个用空间换时间的策略优化,把O(n)的时间降为O(1)。

另外通常我们要记录短网址与长网址的对应的关系,相对于直接存储短网址的而言,存储对应的数值ID会更省空间。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 两种JAVA实现短网址服务算法

    短网址(Short URL) ,顾名思义就是看起来很短的网址.自从twitter推出短网址服务以后,各大互联网公司都推出了自己的短网址服务.短网址最大的优点就是短,字符少,便于发布.传播.复制和存储. 通过网上的搜索,感觉流传了2种短网址算法,一种是基于MD5码的,一种是基于自增序列的. 1.基于MD5码 : 这种算法计算的短网址长度一般是5位或者6位,计算过程中可能出现碰撞(概率很小),可表达的url数量为62 的5次方或6次方.感觉google(http://goo.gl),微博用的是类似这

  • java短网址服务(TinyURL)生成算法

    前不久做了一个优惠劵的分享功能,其中一个功能就是生成一个优惠劵分享短链接.生成的短链接要求每个链接都是唯一的,并且长度尽可能短.在网上查了一下相关的思路,发现了一个不错的算法.这个算法的思路就是用[a-zA-Z0-9]建立一个长度为62的矩阵,然后把矩阵打乱,再生成一个全局唯一的数字,再把这个数字用矩阵内的元素表示转换成62进制,生成的链接长度最大才11位.所以短链接的生成关键点就变成了如何生成一个全局唯一的数字和实现进制的转换. 1.生成全局唯一的数字 这本质是一个分布式ID的问题.如果简单处

  • Java一个简单的红包生成算法

    一个简单的红包生成算法,代码如下: /** * 红包 * @param n * @param money 单位:分 * @return **/ public static double[] redPacket(int n, double money) { // 红包结果 double[] result = new double[n]; // 随机数 double[] randNum = new double[n]; // 随机总数 double randSum = 0; // 保证每个人都分到一

  • PHP利用DWZ.CN服务生成短网址

    使用DWZ.CN生成短网址 <?php /** * FunctionHelper */ class FunctionHelper { // -------------------------------------------------------------------- /** * httpPost * * @param string $url * @param array $param * @return array|bool */ public static function http

  • PHP将URL转换成短网址的算法分享

    前言 短网址服务,可能很多朋友都已经不再陌生,现在大部分微博.手机邮件提醒等地方已经有很多应用模式了,并占据了一定的市场.估计很多朋友现在也正在使用. 短链接的好处: 1.内容需要: 2.用户友好: 3.便于管理. 下面是用PHP实现短网址转换的算法,代码如下: PHP <?php //短网址生成算法 class ShortUrl { //字符表 public static $charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij

  • PHP生成短网址的3种方法代码实例

    短网址服务,可能很多朋友都已经不再陌生,现在大部分微博.手机邮件提醒等地方已经有很多应用模式了,并占据了一定的市场.估计很多朋友现在也正在使用. 看过新浪的短连接服务,发现后面主要有6个字符串组成. 太多算法的东西,也没必要去探讨太多,最主要的还是实现,下面是三种方法的代码: <?php //纯随机生成方法 function random($length, $pool = '') { $random = ''; if (empty($pool)) { $pool = 'abcdefghkmnpq

  • java实现短地址服务的方法(附代码)

    假设下面是你的视频网站链接列表,如果别人想爬取你的数据十分轻松,看规则就知道数据库是序列自增的 http://www.xxxx.com/video/1 http://www.xxxx.com/video/2 http://www.xxxx.com/video/3 那么解决这一问题,我们可以使用短地址,不对外暴露真实链接,使用对称加密是一个很好的方案. Hashids是一个很好的选择,它提供了JS/PHP/JAVA/PYTHON等编程语言的实现,这里我使用的就是它. 下面是我基于blade框架搭建

  • 短网址的原理与生成方法(Java实现)

    短网址应用已经在全国各大微博上开始流行了起来.例如QQ微博的url.cn,新郎的sinaurl.cn等. 我们在QQ微博上发布网址的时候,微博会自动判别网址,并将其转换,例如:http://url.cn/2hytQx 为什么要这样做的,原因我想有这样几点: 微博限制字数为140字一条,那么如果我们需要发一些连接上去,但是这个连接非常的长,以至于将近要占用我们内容的一半篇幅,这肯定是不能被允许的,所以短网址应运而生了. 短网址可以在我们项目里可以很好的对开放级URL进行管理.有一部分网址可以会涵盖

  • PHP生成短网址的思路以及实现方法的详解

    短网址流行已经有一段时间了,尤其是在新浪微博上更是频繁出现,但应该很多人都不知道这个东东是怎么实现的,其实短网址也挺容易的.下面我们对于生成短网址的思路以及使用php生成短网址的实现方法描述一下. 生成短网址的思路:如果把短网址还原了,你知道是个什么样子的吗?可能你看到新浪微博应用里面的短网址都是这个样子: http://t.cn/RzddsXt 其实他还原了说不定就是这个样子: http://t.cn/link.php?url=//www.jb51.net/ 按这个格式可以知道这个短网址其实是

  • PHP通过调用新浪API生成t.cn格式短网址链接的方法详解

    本文实例讲述了PHP通过调用新浪API生成t.cn格式短网址链接的方法.分享给大家供大家参考,具体如下: 新浪提供了长链接转为短链接的API,可以把长链接转为 t.cn/xxx 这种格式的短链接. API: http://api.t.sina.com.cn/short_url/shorten.json (返回结果是JSON格式) http://api.t.sina.com.cn/short_url/shorten.xml (返回结果是XML格式) 请求参数: source 申请应用时分配的App

随机推荐