章节

使用Go语言开发一个短链接服务:一、基本原理  

使用Go语言开发一个短链接服务:二、架构设计

使用Go语言开发一个短链接服务:三、项目目录结构设计

使用Go语言开发一个短链接服务:四、生成code算法

使用Go语言开发一个短链接服务:五、添加和获取短链接

使用Go语言开发一个短链接服务:六、链接跳转

  源码:https://gitee.com/alxps/short_link

  上一篇介绍了项目目录接口,这篇将实现短链接code算法。

前言

  假如某个用户,有个长链接为:https://github.com/gin-gonic/gin/blob/master/internal/bytesconv/bytesconv_1.19.go,我们短链接服务域名为https://a.b.c,为这个长链接生成对应的短链接为https://a.b.c/N26jas。这里code便是Na6jas。

  code必须满足以下几个要求:

    1、只包含,大小写字母或数字

    2、短

    3、唯一

  大小字母加上数字,共62个,当code长度为N时,code可以有62的N次方个。N为5、6、7,code个数大约为1600万, 568亿, 3.5万亿。586亿够用,因此系统code长度为6,够短。

如何生成唯一code

  这还不简单!生成6位随机大小写字母或数字的字符,数据库存在,重新随机生成,递归直到不冲突。本篇完……,当然不是。

  至于如何生成6位随机大小写字母或数字,可以看看这篇文章:Golang 生成随机字符串的八种方式与性能测试。文章随机字符串只有大小写字母,我们在此基础上稍作修改,代码如下:

package service

import (
"math/rand"
"time"
"unsafe"
) const letters = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" var src = rand.NewSource(time.Now().UnixNano()) const (
// 6 bits to represent a character index
charIdBits = 6
// All 1-bits as many as charIdBits
charIdMask = 1<<charIdBits - 1
// 由于现在包含了62个字符,计算新的charIdMax
charIdMax = 63 / charIdBits
// 字符集的大小
charsetSize = len(letters)
) func randStr(n int) string {
b := make([]byte, n)
for i, cache, remain := n-1, src.Int63(), charIdMax; i >= 0; {
if remain == 0 {
cache, remain = src.Int63(), charIdMax
}
if idx := int(cache & charIdMask); idx < charsetSize {
b[i] = letters[idx]
i--
}
cache >>= charIdBits
remain--
}
return unsafe.String(unsafe.SliceData(b), len(b))
}

  但是,我想法是,code要根据用户id和长链接url推算出来,即相同的user_id+long_url,每次得到的code都一样。先上代码,再讲思路

package service

import (
"crypto/md5"
"encoding/hex"
"hash/fnv"
"io"
"unsafe" "github.com/1911860538/short_link/config"
) const letters = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" var confCodeLen = config.Conf.Core.CodeLen // GenCode
func GenCode(userId string, longUlr string, salt string) (string, error) {
// 首先对userId+longUrl+salt md5 主要为了防止longUrl包含汉字等字符串
hasher := md5.New()
if _, err := io.WriteString(hasher, userId+longUlr+salt); err != nil {
return "", err
}
hashStr := hex.EncodeToString(hasher.Sum(nil)) stepLen := len(hashStr) / confCodeLen
remain := len(hashStr) % confCodeLen
if remain > 0 {
stepLen += 1
}
lettersLen := uint32(len(letters))
b := make([]byte, confCodeLen) for i := 0; i < confCodeLen; i++ {
// 根据要生成的code长度,切分md5字符串
var piece string
if remain > 0 && i == confCodeLen-1 {
piece = hashStr[i*stepLen : i*stepLen+remain]
} else {
piece = hashStr[i*stepLen : i*stepLen+stepLen]
} // 为切片元素生成对应的整形数值
h := fnv.New32a()
pieceBytes := unsafe.Slice(unsafe.StringData(piece), len(piece))
if _, err := h.Write(pieceBytes); err != nil {
return "", err
}
pieceHash32 := h.Sum32() // 切片字符的整形,取len(letters)余数,并取letters索引为该余数的letter
letterIdx := pieceHash32 % lettersLen
b[i] = letters[letterIdx]
} return unsafe.String(unsafe.SliceData(b), len(b)), nil
}

  比如user_id为"1f70a466-1449-4676-b2d7-2037341c718e",long_url为"https://i.cnblogs.com/posts/edit;postId=18090256":

    1、将user_id+long_url字符串,生成md5的哈希字符串,这一步是为了得到固定长度的字符。结果为,"101360eb993b977d9f6969813ee84338"

    2、根据要生成的code长度,切分步骤1的字符串。我们要得到6位code,因而我们将得到的字符切片结果为,["101360", "eb993b", "977d9f", "696981", "3ee843", "38"]

    3、接着我们对步骤2每个字符切片元素,使用fnv哈希,获得uint32,结果为[791694210, 3988549581, 2254501405, 2706880430, 3291227237, 2414894606]

    4、对步骤3,uint32切片,每个元素,取letters长度余数,获得余数切片,[28, 53, 55, 48, 17, 0]

    5、取letters索引为步骤4余数切片的字母或数字字符,得到最终结果,"2RTMra"

  步骤3/4参考了一致性哈希。当然,上面两种获取6位code方式凭个人想法哈,网上也有其它算法实现可参考。本项目中使用上面说的后者。

总结

  本篇讲了短链接code生成逻辑,下一篇讲添加和获取短链接逻辑。

使用Go语言开发一个短链接服务:四、生成code算法的更多相关文章

  1. 百度 谷歌 Twitter,这么多短链接服务(Short Url)究竟哪家强?

    一.短链接是什么 url=HPqdQ5VR3vA39x7ZWoWyNzwWnsDhTbh66BTpdzsJLroBDzFRm4JV-G818Zc027uZrwe7zxtxnD4H2FUahftpUK& ...

  2. 用PHP和Python生成短链接服务的字符串ID

    假设你想做一个像微博短链接那样的短链接服务,短链接服务生成的URL都非常短例如: http://t.cn/E70Piib, 我们应该都能想到链接中的E70Piib对应的就是存储长链接地址的数据记录的I ...

  3. Knative 实战:三步走!基于 Knative Serverless 技术实现一个短网址服务

    短网址顾名思义就是使用比较短的网址代替很长的网址.维基百科上面的解释是这样的: 短网址又称网址缩短.缩短网址.URL 缩短等,指的是一种互联网上的技术与服务,此服务可以提供一个非常短小的 URL 以代 ...

  4. Java 网址短链接服务原理及解决方案

    一.背景 现在在各种圈的产品各种推广地址,由于URL地址过长,不美观.不方便收藏.发布.传播以及各种发文字数限制等问题,微信.微博都在使用短链接技术.最近由于使用的三方的生成.解析短链接服务开始限制使 ...

  5. 短链接服务Octopus的实现与源码开放

    前提 半年前(2020-06)左右,疫情触底反弹,公司的业务量不断提升,运营部门为了方便短信.模板消息推送等渠道的投放,提出了一个把长链接压缩为短链接的功能需求.当时为了快速推广,使用了一些比较知名的 ...

  6. 最近做了一个短网址服务 di81.com

    最近做了一个短网址服务:   di81.com 项目中有一处需求,需要把长网址缩为短网址,把结果通过短信.微信等渠道推送给客户.刚开始直接使用网上现成的开放服务,然后在某个周末突然手痒想自己动手实现一 ...

  7. 使用plv8+hashids生成短链接服务

    有写过一个集成npm plv8 以及shortid生成短链接id服务,实际上我们可以集成触发器自动生成url对应的短链接地址,hashids也是一个不错的选择. 以下是一个别人写的一个博客实现可以参考 ...

  8. 使用go语言开发一个后端gin框架的web项目

    用liteide来开发go的后端项目,需要注意的是环境变量要配置正确了 主要是GOROOT, GOPATH, GOBIN, PATH这几个, GOPATH主要用来存放要安的包,主要使用go get 来 ...

  9. ubuntu下使用C语言开发一个cgi程序

    主要步骤是: 1. 开发一个C程序(在标准输出中输出HTML字符串) 2. 复制到apache2的cgi-bin目录去 3. 在httpd.conf中开启cgi功能(我似乎没用到,也可以使用cgi) ...

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

          前不久做了一个优惠劵的分享功能,其中一个功能就是生成一个优惠劵分享短链接.生成的短链接要求每个链接都是唯一的,并且长度尽可能短.在网上查了一下相关的思路,发现了一个不错的算法.这个算法的思 ...

随机推荐

  1. NC16645 [NOIP2007]矩阵取数游戏

    题目链接 题目 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵 ...

  2. SavedStateHandle的介绍----ViewModel不具备保存状态数据的功能

    LiveData本身不能在进程销毁中存活,当内存不足时,Activity被系统杀死,ViewModel本身也会被销毁. 为了保存LiveData的数据,使用SavedStateHandle. 事故场景 ...

  3. OGP协议的使用

    OGP协议是一套Metatags的规格,用来标注页面,告诉我们你的网页快照.帮助社交app高效并准确的获取网页中的核心链接.标题.主图.正文摘要等信息,使得该网页在社交分享中有更好的展现体验. 如果网 ...

  4. 子集 II

    子集 II 给定一个可能包含重复元素的整数数组nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例 输入: [1,2,2] 输出: [ [2], [1], [1,2,2] ...

  5. Java设计模式-代理模式Proxy

    介绍 代理模式是一种比较好理解的设计模式.简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能. ...

  6. mongodb(2022)

    了解 文档数据库MongoDB用于记录文档结构的数据,如JSON.XML结构的数据.一条文档就是一条记录(含数据和数据结构),一条记录里可以包含若干个键值对.键值对由键和值两部分组成,键又叫做字段.键 ...

  7. 【Java复健指南10】OOP高级01-类变量、类方法和main

    类变量 什么是类变量 类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量. 如何定义类变 ...

  8. 第一百一十三篇: JS数组Array(二)数组方法 栈、队列、排序

    好家伙,    在上一篇中,我们知道了, JS的数组中每个槽位可以存储任意类型的数据 那么,我们能通过数组去模仿某些数据结构吗? 答案是肯定的 1.栈方法 ECMAScript 给数组提供几个方法,让 ...

  9. 【Azure 应用服务】Python3.7项目在引用pandas 模块后,部署报错 

    问题描述 参考"快速入门:在 Linux 上的 Azure 应用服务中创建 Python 应用" 文档,在App Service For Linux环境中部署Python应用,在添 ...

  10. 【Azure 环境】使用Azure中的App Service部署Web应用,以Windows为主机系统是否可以启动防病毒,防恶意软件服务呢(Microsoft Antimalware)?

    问题描述 使用Azure中的App Service部署Web应用,以Windows为主机系统是否可以启动防病毒,防恶意软件服务呢? Microsoft Antimalware for Azure is ...