背景
需要设计一个短链接系统,主要功能主要有如下几点:
ToB:
- 输入一个长链接,转换成短链接。
- 这个短链接有时效性,可以设定指定过期时间。
- 这个系统的每天会生成千万级别的短链接。
- 数据具备可分析功能。
ToC:
- 用户可以通过短链接访问到长链接。
- 系统每天访问链接的流量在10亿QPS。
问题
通过上述背景,我们可以分析出以下几个问题:
- 长链接如何转化成短链接,短链接又如何映射成长链接?
- 短链接的时效性如何保证?
- 系统每天的读写很高,怎么保证系统的稳定性和可用性?
- 数据可分析,数据就要持久化,用什么样的数据库?
方案
针对上述提到的问题,我们来逐一分析。
链接转化
如何将长链接转换成短链接,目前已经有很多开源工具都可以支持。
-
C1N短网址(c1n.cn)
-
Bitly
-
TinyURL
-
Rebrandly
-
Shorte.st
-
T2M
-
ClickMeter
-
Ow.ly
如上图,我们将长链接转换成了短链接,整个URL都变了,域名也变了,所以我们需要有自己的独立域名,根据后面的k5C6M
找到原始的长链接,进行重定向即可。
我们可以为每一个长链接生成一个全局唯一ID,通过ID可以定位到具体的链接,此时我们只需要根据ID,就可以找到原始长链接,然后将流量重定向即可。
每天庞大的数据生成,需要考虑到ID的生成策略,和数据量的支持,以及短链接的不可预测功能。
这里给出一种策略,可以基于TDDL的全局唯一序列思想生成ID,比如,我们设定全局唯一ID的长度为19位,组成方式为2+13+4;前两位短链接标识符,中间13位为全局唯一序列,后4位为随机数,保证ID的不可预测。
虽然这样很好了,但是19位数字也有点太长了,我们将这19位数字转换成64进制,这样就短了一些。
这样我们就完成了链接转化。
链接时效
链接时效,我们很容易想到使用Redis,同时Redis也可以保证系统的读写性能,Redis单机的读写QPS能到10万级。
我们系统每天的QPS有10亿,每天10亿流量,是在一段时间内集中?还是全天比较平均?假设一天在4小时内流量比较聚集,平均每秒的QPS有6万。
做好Redis的高可用主从架构,抗住这些流量问题不大,但是Redis里的数据是会过期的,
我们的数据该如何分析呢?
数据分析
数据的持久化,我们有很多方式:Redis、MySQL、离线表等。
Redis虽然有持久化机制,但是数据具有时效性,随时会过期。
MySQL可以,但是数据量这么庞大,并且我们只是为了做数据分析,对数据的实时性要求并不高,所以MySQL也不考虑。
离线表非常适合我们的诉求,成本又低,又可以存大量数据。但是我们在什么时候存进去呢?
我们可以在缓存失效的节点将数据存进去,具体方案:
- 监听Redis缓存失效事件
- 考虑到流量突增的情况,应用层通过MQ处理该事件
- 监听MQ,将数据写入离线表。