系统描述

一般我们使用的http链接,本身的uri很长而且会带有一些业务含义,而且再加上一些querystring之后,整个url字符串会达到几百个字符长度,在需要链接传递,且对内容长度敏感的场景下,比如发的短信中包涵链接,会带来安全问题,以及不必要的saas成本。
所以我们一般会通过增加一层(优化法则第一条:遇事不决加一层)映射代理,使长连接变短来解决这个问题。
此外可能还有扩展需求:

  1. 特定短链保留
  2. 短链过期设计
  3. 短链密码设计

    关注点

  4. 超大数据量,比如亿级别的数量,也就是如何解决存储问题。

  5. 超高并发量,比如w级别的QPS,也就是如何解决性能问题。

    分析点

  6. 本系统本质上就是对映射关系的读写操作,逻辑非常简单,所以是IO密集场景。

  7. 读写比很大,所以是典型的读多写少的场景。
  8. 因为是映射关系,链接的唯一性是需要核心保证的,所以需要设计全局唯一性。
    1. 一个短链接只能唯一解析成一个长链接,这事肯定的,否则就无法运行了。
    2. 但一个长链接是不是只能对应一个短链接呢,不一定:
      1. 首先在技术方面,不推荐在长链接入库的时候还需要先查询一下是否已存在映射关系,因为一般短链接系统的索引是建在短链接字段上的而不是长链接,所以反查会影响写性能。
      2. 其次在业务方面,也更推荐相同长链接对应不同的短链接,因为短链接的除了重定向还有一个核心功能是访问统计,所以相同长链接可以基于创建用户、创建时间等更多维度来划分,便于后续统计。
  9. 还有当然需要短。
  10. 需要在长短链接之间做302重定向处理。
  11. 需要关注高可用设计,因为一旦数据丢失或系统宕机,会严重影响上游系统。

    解决方案

    表设计

    | 字段 | 描述 | | —- | —- | | short_url | 短链接 | | origin_url | 源链接 | | creater | 创建人 | | create_time | 创建时间 | | expire_time | 过期时间 |

mysql

  1. mysql能存储数据,且天然支持高可用设计。
  2. mysql能解决唯一性问题,不管通过单机下的表主键还是分布式下雪花算法,都可以生成唯一ID。
  3. mysql在主键查询的下的性能比较好。

    redis

  4. redis能存储数据,且天然支持高可用设计。

  5. redis自带过期能力实现。
  6. redis需要自己设计唯一性算法,比如哈希算法,如MD5,BASE64等。
  7. redis的读写性能非常好,但是超大规模数据量的存储,对内存资源的配置成本要求较高。