今天刚收到一个短信,里面就有一个短域名。
这个短域名的目的很简单,为了在发短信的时候能省点钱,并且让用户体验不要那么糟糕,动不动发一个几百个字符的URL,小白用户一脸懵逼。其实短域名的原理非常简单,当你访问这个段域名的时候,短域名服务器会给你重定向到到真实的URL,浏览器会自动跳转到这个真实的URL。
那么如何设计这样一个短域名服务呢?下面谈谈我个人的设想。第一个需要解决的问题,是如何生成这样一个短域名随机串。我们可以通过随机函数从 [a-z 0–9 A-Z] 这 62 字符(尽管中划线和下划线也是合法字符)里面随意的组合,那么它有多少种可能呢?
如果是 7 未随机串 62⁷ = 3,521,614,606,208 urls 如果是 8 位随机串 62⁸ = 218,340,105,584,896 urls
可以看到 8 为的随机串已经可以代表很多URL 了。这里可以通过redis 帮我们生成一个随机的hash key。 整个短域名的结构可以如下定义:
hash_key 随机值 original_url 原生URL shorten_url 短域名URL creation_date 创建时间 expiration_date 有效时间
当创建一个短域名后,我们就会生成上面的一条记录,然后保存到 mysql 并缓存到redis 里面。当短域名的请求到来时,就从redis 里面匹配短域名,获取真实 URL 并通过 302 返回给客户端。
这里最后还需要做容量评估,如果我们的系统,每月新增 10 亿个短域名,那么平均每秒需要插入 386 个URL。
1000 million / (30 days * 24 hours * 3600 seconds) = ~386 URLs/s
QPS评估
按照每个URL被访问100 计算,每秒也就 38k,由于这个系统结构非常简单,每秒4万个请求应该还是比较容易搞定的。
100 billion / (30 days * 24 hours * 3600 sec) = ~38K/s
流量评估
如果我们按照每个完整URL 500byte来算
38K * 500 bytes = ~18 MB/s
这个带宽要求还是有点高的,因为如果单纯这一个服务就需要18 M带宽,我更加建议在公有云上单独部署这样一个服务。
存储评估
如果按照URL 保存两年来计算 每月是10 亿 * 24 个月
24 billion * 500 bytes = 12 TB
12T 的存储容量对应数据库来说也能承受,因为大部分短域名都是近期有效,redis能够挡住大部分流量。
至于内存评估,这个主要看redis 的容量了,最好能缓存近期一个月以内的短域名,也就需要 500G。
为了防止恶意的请求,我还想在前面加一个waf 防火墙,限制每个源IP 每秒可以请求 3 次,基本上人为的点击应该差不多。或者可以在请求redis之前做一层布隆过滤,发现短域名不存在就直接返回,虽然有极小的误判概率基本可以忽略。
上面说的都是我个人YY的,大家有啥好的改进意见嘛 ?